5

It seems that awk script considers ARGV[1] to ARGV[ARGC] as input files.

Is there any way to make awk considering ARGV as simple arguments instead of an input file

Example:

test.awk

#!/usr/bin/awk -f
BEGIN {title=ARGV[2]}
{if ($1=="AA") {print title}}

dat file

AB
BA
AA
CC

$ test.awk dat 'My Interesting Title'

My Interesting Title awk: test.awk:3: fatal: cannot open file `My Interesting Title' for reading (No such file or directory)

Fredrik Pihl
  • 44,604
  • 7
  • 83
  • 130
Alain
  • 53
  • 1
  • 3

5 Answers5

9

You can modify ARGV at any time. Awk processes the elements of ARGV in turn, so if you modify them during processing, you can arrange to read different files or not to treat some arguments as file names. In particular, if you modify ARGV in the BEGIN block, anything is possible. For example, the following snippet causes awk to read from standard input even when arguments were passed, and saves the arguments in an array called args:

awk '
    BEGIN {for (i in ARGV) {args[i] = ARGV[i]; delete ARGV[i]}}
    …
' hello world

If you just want to skip the first argument, delete it only:

awk '
    BEGIN {title = ARGV[1]; delete ARGV[1]}
    $1 == "AA" {print title}
' 'My Interesting Title' input.txt

However, this is unusual and therefore may be considered hard to maintain. Consider using a shell wrapper and passing the title through an environment variable instead.

#!/bin/sh
title=$1; shift
awk '
    $1 == "AA" {print ENV["title"]}
' "$@"

You can also pass a string as an awk variable. Beware that the value undergoes backslash expansion.

awk -v 'title=My Interesting Title\nThis is a subtitle' '
    $1 == "AA" {print title}  # prints two lines!
' input.txt
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
3

Something like this?

$ awk -v title='My Interesting Title' '$0 ~ /AA/ {print title}1' input
AB
BA
My Interesting Title
AA
CC
Fredrik Pihl
  • 44,604
  • 7
  • 83
  • 130
1

Yes:

BEGIN{title=ARGV[2];ARGV[--ARGC]=""}
$1=="AA" {print title}

but you probably want this instead:

$ cat tst.sh
awk -v title="$2" '$1=="AA" {print title}'

See http://cfajohnson.com/shell/cus-faq-2.html#Q24 for details on those and the other ways to pass the value of shell variables to awk scripts.

As an aside, note that whether you use this script or your original, the contents of your file is a shell script that calls awk, not an awk script, so the suffix should not be .awk, it should be .sh or similar.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
1

You can decrement ARGC after reading arguments so that only the first(s) argument(s) is(are) considered by awk as input file(s) :

#!/bin/awk -f

BEGIN {
    for (i=ARGC; i>2; i--) {
        print ARGV[ARGC-1];
        ARGC--;
    }
}
…

Or alternatively, you can reset ARGC after having read all arguments :

#!/bin/awk -f

BEGIN {
    for (i=0; i<ARGC; i++) {
        print ARGV[ARGC-1];
    }
    ARGC=2;
}
…

Both methods will correctly process myawkscript.awk foobar foo bar … as if foobar was the only file to process (of course you can set ARGC to 3 if you want the two first arguments as files, etc.).

Skippy le Grand Gourou
  • 6,976
  • 4
  • 60
  • 76
0

allow also

awk 'BEGIN {title=ARGV[2]}
           {if ($1=="AA") {print title}}
    ' input.txt -v "title=My Interesting Title"

argument for ARGV are also any string (argument of command line) of format varname=VarContent

NeronLeVelu
  • 9,908
  • 1
  • 23
  • 43