48

If I want to pass a parameter to an awk script file, how can I do that ?

#!/usr/bin/awk -f

{print $1}

Here I want to print the first argument passed to the script from the shell, like:

bash-prompt> echo "test" | ./myawkscript.awk hello
bash-prompt> hello
Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
Mahmoud Emam
  • 1,499
  • 4
  • 20
  • 37

3 Answers3

65

In awk $1 references the first field in a record not the first argument like it does in bash. You need to use ARGV for this, check out here for the offical word.

Script:

#!/bin/awk -f

BEGIN{
    print "AWK Script"
    print ARGV[1]
}

Demo:

$ ./script.awk "Passed in using ARGV"
AWK Script
Passed in using ARGV
Julian Reschke
  • 40,156
  • 8
  • 95
  • 98
Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
  • 1
    Note: ARGC and ARGV built-in variables are not available in version of awk included in BSD and macOS. They are available in GNU awk (gawk) – AliA Jun 26 '19 at 00:18
  • @AliA This is ***false***. I am macOS 13.2 (which has BSD's flavor of awk I believe) and it is documented. It is also apart of [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html). – tmillr Apr 22 '23 at 21:12
  • @tmillr You are right. It is available in macOS 12.6.1 as well – AliA Apr 25 '23 at 21:07
47

You can use -v as a command-line option to provide a variable to the script:

Say we have a file script.awk like this:

BEGIN {print "I got the var:", my_var}

Then we run it like this:

$ awk -v my_var="hello this is me" -f script.awk
I got the var: hello this is me
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • 3
    IMO, this is the only answer that really addresses the question. To add to this, you can still do this if your script is executable: `cat file | script.awk -v my_var="hello this is you"` – xdhmoore Aug 08 '17 at 20:59
24

your hash bang defines the script is not shell script, it is an awk script. you cannot do it in bash way within your script.

also, what you did : echo blah|awk ... is not passing paramenter, it pipes the output of echo command to another command.

you could try these way below:

 echo "hello"|./foo.awk file -

or

var="hello"
awk -v a="$var" -f foo.awk file

with this, you have var a in your foo.awk, you could use it.

if you want to do something like shell script accept $1 $2 vars, you can write a small shellscript to wrap your awk stuff.

EDIT

No I didn't misunderstand you.

let's take the example:

let's say, your x.awk has:

{print $1}

if you do :

echo "foo" | x.awk file

it is same as:

echo "foo"| awk '{print $1}' file

here the input for awk is only file, your echo foo doesn't make sense. if you do:

  echo "foo"|awk '{print $1}' file -
or
    echo "foo"|awk '{print $1}' - file

awk takes two input (arguments for awk) one is stdin one is the file, in your awk script you could:

echo "foo"|awk 'NR==FNR{print $1;next}{print $1}' - file

this will print first foo from your echo, then the column1 from file of course this example does nothing actual work, just print them all.

you can of course have more than two inputs, and don't check the NR and FNR, you could use the

ARGC   The number of elements in the ARGV array.

ARGV   An array of command line arguments, excluding options and the program argument, numbered from zero to ARGC-1

for example :

echo "foo"|./x.awk file1 - file2

then your "foo" is the 2nd arg, you can get it in your x.awk by ARGV[2]

echo "foo" |x.awk file1 file2 file2 -

now it is ARGV[4] case.

I mean, your echo "foo"|.. would be stdin for awk, it could by 1st or nth "argument"/input for awk. depends on where you put the -(stdin). You have to handle it in your awk script.

Kent
  • 189,393
  • 32
  • 233
  • 301
  • 1
    You have misunderstanding, you understand that echo blah | awk ... means I am passing parameter to awk script. Read again. – Mahmoud Emam Apr 12 '13 at 11:51
  • 1
    nice upvoted comment :).. @UNIX see edit, i hope it is cleared now. – Kent Apr 12 '13 at 12:20
  • @UNIX shortly, if you want your `echo foo|./x.awk file` to print `foo` first, do `echo foo|./x.awk - file` – Kent Apr 12 '13 at 12:32
  • Came back to this answer (I favorited the question to do so). I cannot do something like `awk {print 1}`. Does it means that `awk` always needs either `awk file` or `something | awk `? – fedorqui Apr 26 '13 at 09:22
  • @fedorqui sure you can do it without input. `awk 'BEGIN{print "kent"}'` – Kent Apr 26 '13 at 09:25
  • Ah, I see. It has to be within the `BEGIN` block, otherwise it expects some stdin. That makes my day (awklly talking :D). Thanks, @Kent! – fedorqui Apr 26 '13 at 09:29