GNU awkはパラメータをパスとして扱おうとします。

GNU awkはパラメータをパスとして扱おうとします。

以下の最小限の例がありますawk

#!/usr/bin/awk -f
BEGIN {
  if (ARGC>1)
    a=ARGV[1]
  else
    a=5
}

{
  print
}

で呼び出すと、次のようにls -l|./t.awkなります。

$ ls -l|./t.awk 2
awk: ./t.awk:4: fatal: cannot open file `2' for reading (No such file or directory)

Argument() なしで呼び出すとls -l|./t.awk問題はありません。

だから最初の質問は、単純な文字列同一性チェックの代わりに「2」というファイルを読み取ろうとすることです。

2番目の驚くべきことは、2番目のブロックを削除すると正常に動作することです! (空の出力を提供します。)

#!/usr/bin/awk -f
BEGIN {
  if (ARGC>1)
    a=ARGV[1]
  else
    a=5
}

なぜですか?

答え1

awkはパラメータを提供しますが、最終的に必要に応じてパラメータを操作できます。たとえば、argを空白に設定します。

if (ARGC>1) {a=ARGV[1]; ARGV[1]=""}
else a=5

それ以外の場合、argsはオプションではなくエントリの入力ファイル名である一般的な機能を持ちます。したがって、awkは「2」ファイルを読み取り、そのファイルからスクリプト本文を実行しようとします。

答え2

コマンドラインでawkに引数を渡すと、awkはファイルを提供すると想定してそのファイルを開こうとします。私はあなたが何が起こるのを期待しているのか本当に理解していません。これがawkが通常行動する方法です。

削除すると、機能する理由{ print }も簡単です。これを削除すると、BEGIN{}入力ファイルを読み取る前に実行される単一のブロックが残ります。それ以外には何もないので、BEGIN{}ファイルを読み取ろうとする理由はなく、プログラムが終了します。これは次の方法で簡単に確認できますstrace

$ strace awk 'BEGIN{a=1}{print}' somefile |& grep 'open.*somefile'
openat(AT_FDCWD, "somefile", O_RDONLY)  = -1 ENOENT (No such file or directory)
write(2, "cannot open file `somefile' for "..., 66cannot open file `somefile' for reading: No such file or directory) = 66

上記を以下と比較してみてください。

$ strace awk 'BEGIN{a=1}' somefile |& grep 'open.*somefile'
$ 

ファイルに対して何もする必要はないので、ファイルを開こうとしません。


あなたが探しているのは、foo=barコマンドラインで変数を渡すことができる形式だと思います。

ls -l|./t.awk a=2

次に、スクリプトを次のように変更します。

#!/bin/awk -f
BEGIN {
  if (!a){
    a=5
  }
}

{
  print a,$0
}

そしてそれがどのように機能するかを説明してください:

$ echo foo | t.awk          ## default value
5 foo
$ echo foo | foo.awk a=12   ## value given at launch
12 foo

または、このオプションを使用してコマンドラインから直接実行するときに-v同じことを実行できます。

$ awk -v a=12 'BEGIN{print a}'
12

関連情報