web-dev-qa-db-ja.com

Awkスクリプトを本当に終了する

PerlとRuby exitは実際に終了します:

$ Perl -e 'BEGIN {print 1; exit}; END {print 2}'
1

$ Ruby -e 'BEGIN {print 1; exit}; END {print 2}'
1

Awkはそうではありません:

$ awk 'BEGIN {print 1; exit}; END {print 2}'
1
2

「help.awk」でこれを解決しようとしました

function really_exit() {
  IM_SURE = 1
  exit
}
END {
  if (IM_SURE) {
    exit
  }
}

しかし、これはそれ自身の問題を引き起こします。 「prog.awk」に開始ブロックしかない場合:

BEGIN {
  print "start"
}

次にそれを実行します:

awk -f help.awk -f prog.awk

入力を待ってハングします。 Awkスクリプトを実際に終了するためのより良いソリューションはありますか?

3
Steven Penny

Awkプログラムに「middle」またはENDブロックがある場合、入力が読み取られます。 null入力を提供することでこれに対抗できます。

$ cat prog.awk
1
END {
  print "fin"
}

$ awk -f prog.awk /dev/null
fin

これをデフォルトにしたい場合は、「help.awk」にブロックを追加できます。

BEGIN {
  if (ARGC == 1 && !system("[ -t 0 ]")) {
    ARGV[ARGC++] = "/dev/null"
  }
}

ただし、これにより重要な変更が発生します。ダッシュを追加しない限り、awkはターミナルから読み取りを行いません。

awk -f help.awk -f prog.awk -

または「prog.awk」を変更します。

getline < "-"

入力の読み取り例:

$ cat prog.awk
/4/ {
  really_exit()
}
1
END {
  print "fin"
}

$ seq 10 | awk -f help.awk -f prog.awk
1
2
3

入力を読み取らない例:

$ cat prog.awk
BEGIN {
  print "start"
  really_exit()
}
END {
  print "fin"
}

$ awk -f help.awk -f prog.awk
start
2
Steven Penny