0

I have a simple awk script, test1.awk:

{
    x=temp;
    print x;
}

When I run it from the Command Prompt with:

awk -v temp=hello -f test1.awk

I get just a cursor.  I hit Enter, it writes “hello” and gives another cursor, hit Enter again and it writes “hello” again, etc.  Just goes in an endless loop requiring input from the user, and never comes back to the command prompt.

D:\>awk -v temp=hello -f test1.awk

hello

hello

hello

hello
^C
D:\>

How do I get it write “hello” (without requiring user input) and then stop?

  • Your example is simultaneously complex and trivial.   It is complex in the sense that it has a variable that must be set via -v, or else the program won’t do anything, and then it copies that variable to another variable for no real functional purpose.   It is trivial in the sense that it does nothing but print the value of that variable.   When you’re debugging / troubleshooting, trivial is good and complex is bad.   For trying to get something (anything) to work, you should probably start with trivial things like { print "Hello"; }.   For a slightly less trivial example, see my answer. – Scott Oct 27 '18 at 2:26
1

Awk reads from stdin. When you run awk as you are doing above, the awk script is going to process stdin. You did not pass it in any file to process. If you have a file, test.in for example, you can run your awk program as follows:

awk -v temp=hello -f test1.awk test.in

The awk script will process test.in and exit.

Hope this helps.

  • Thanks, what must I put in test.in? – dacfer Oct 22 '18 at 17:42
  • What are you trying to do with your awk script? – Lewis M Oct 22 '18 at 17:47
  • I am trying to use awk to interpret an environment variable, net_args: net_args=debug=(123,456) to see if %1 is in there or not. If it is, then I exit the awk script with exit 1 else exit 0 – dacfer Oct 22 '18 at 17:51
  • so I use: awk -v "temp=%net_args%" -v dflag=%1 -f test.awk test.in. I put junk into test.in and it works, but just wondered what the significance of test.in is. – dacfer Oct 22 '18 at 17:53
  • Then your input can be /dev/null, or whatever the equivalent is on Windows. – Lewis M Oct 22 '18 at 18:38
0

To avoid a pointless input file, you can put the commands in the END clause:

END { x=temp; print x; }

Then call the awk script with /dev/null for input, as suggested by Lewis M:

awk -v temp=hello -f test1.awk </dev/null

Or equivalently in one line:

awk -v temp=hello 'END {x=temp; print x;}' </dev/null
0

You say you want to run some awk statement(s) once, without requiring user input, and then stop and return to the command prompt.  And in your case you are talking about the Command Prompt (cmd.exe in Windows), and not a shell (like bash).

  1. Matthias Gralle’s answer,

    awk -v temp=hello 'END {x=temp; print x;}' < /dev/null

    will work in Unix / Linux, and maybe even in a Unix-like shell in Windows, but not in cmd.exe.  Windows doesn’t have a /dev/null, per se.  But Windows does have a null device, called simply NUL.  (You may add a colon, resulting in NUL:, if you want; it’s optional.  And, as is typical in Windows, this is case-insensitive, so you can say nul.)  So

    awk -v temp=hello 'END {x=temp; print x;}' < nul
    will probably work.

    You don’t say what flavor of awk you have on your Windows machine.  I have Cygwin, and it turns out that I can do

    C:\Users\scott> \cygwin64\bin\gawk -v temp=hello 'END {x=temp; print x;}' /dev/null
    hello
    The difference is that, when you say < filename, the command processor (cmd.exe, in your case) processes the filename, but, if you leave out the < and say just filename, the program processes it.  And it turns out that Cygwin programs interpret /dev/null as being the null device, even if they’re being run from Command Prompt.

    Since I don’t know what flavor of awk you have on your Windows machine, I don’t know whether this will work for you.

  2. Matthias came very close to giving you a really good answer.  As Lewis M explained, awk processes input.  A typical awk program looks something like
    BEGIN { something to do (once) at the beginning of the program }
          { something to do on every line of input }
    /foo/ { something to do on every line of input that contains “foo” }
          { something else to do on every line }
                ︙
    END   { something to do (once) at the end of the program }
    where all of these parts are optional.  (And, as you demonstrated in your question, code blocks (a.k.a. actions) can be broken up into multiple lines.  And short things can be put together on the same line.)  Matthias’s idea is to put your statement(s) into the END code block, and then to provide a null input, so awk will start, execute your statement(s) once, and then exit.  Not that there’s anything wrong with that.  But it turns out that, if your program consists of a BEGIN code block, and nothing else, then awk executes your statement(s) (once) without even trying to read any input.  So you can say
    awk -v temp=hello 'BEGIN {x=temp; print x;}'
    and not need to worry about providing / specifying any input.
  3. Here’s an example of a trivial awk program that’s not too trivial:

    awk '{print "Hello", $0}'

    If you type this and then hit Enter, it will say Hello.  If you type world, it will say Hello world.  If you type Kitty, it will say Hello Kitty©.  As you know, you can get back to your command prompt by hitting Ctrl+C, which basically means “interrupt / stop processing”.  But a “nicer” thing to do is to hit Ctrl+D, which means “this is the end of the input”.  This is standard on Unix & Linux, but I can do the following (where the bold italic text is what I typed):

    C:\Users\scott> \cygwin64\bin\gawk '{print "Hello", $0} END {print "Good bye"}'
    sailor
    Hello sailor
    stranger
    Hello stranger
    Ctrl+D
    Good bye
    whereas, if I hit Ctrl+C, the END code doesn’t run.

    Again, if you’re using something other than Cygwin, I don’t know whether this will work for you.


Throughout the above examples, anything that I put between single quotes ('…') can be put into a file, which you then (as you know) invoke with -f filename.  On Unix, Linux and Cygwin, I prefer to put my awk programs into shell scripts, like

#!/bin/sh
awk '{print "Hello", $0}' "$@"
rather than use .awk files.  The "$@" lets you pass arguments to awk.  You might be able to do that in a Windows batch file with $*, but things are never easy in Windows.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.