Awkでif条件を実装したいだけです。以下のように「simple_if」というファイル名を作成しました。
BEGIN{
num=$1;
if (num%2==0)
printf "%d is Even number.\n",num;
else printf "%d is odd Number.\n",num
}
次に、以下のように$ 1の引数として10を渡してプログラムを実行しました
awk -f simple_if 10
しかし、それは入力をとらず、代わりに0を表示します。出力:
0 is Even number.
Awkでユーザーから値を取得する方法は?
コマンドラインの最後でawk
に指定された引数は、通常、awk
スクリプトが読み取るファイル名として解釈されます。コマンドラインで変数を設定するには、-v variable=value
を使用します。
awk -v num=10 -f script.awk
これにより、num
をスクリプトの変数として使用できるようになります。上記の例では、変数の初期値は10です。
スクリプトでENVIRON["variable"]
を使用して環境変数を読み取ることもできます(variable
という名前の環境変数の場合)、またはARGV[n]
を使用してコマンドライン引数を確認することもできます。ここで、n
は正の整数。
awk
で$1
を使用すると、現在のレコードの最初のフィールドの値を参照できますが、BEGIN
ブロックで使用しているため、データはまだありません任意のファイルから読み取ります。
コード内の数値は、算術コンテキストで使用される空の変数であるため、ゼロとして解釈されています。
$1
は最初のコマンドライン引数ではなく、FS
で行が分割された後の最初のフィールドです(行が分割されなかったため、BEGIN
は空の文字列になります)まだ)。
コマンドライン引数は配列ARGV
にあります:
$ awk 'BEGIN { for(i = 1; i < ARGC; i++) print ARGV[i] }' 1st 2nd 3rd
1st
2nd
3rd
ARGV[0]
は常にインタープリターの名前です(awk
またはgawk
など)。
awk
にコマンドライン引数を無視させ、後でファイルとして開かないようにするには、削除するか、空の文字列に設定する必要があります。 ARGV[1]=""
。
補足として、var=value
という形式の引数もawk
による変数割り当てとして解釈され、評価されますafter先行するファイル引数処理されました:
$ echo yes > file
$ awk '{ gsub(/e/, var); print }' var=1 file var=2 file var=3 file
y1s
y2s
y3s
key=val
という形式の実際のファイル名をawk
とともに使用するには、相対パスまたは絶対パスとして渡す必要があります。 awk '{...}' ./key=val
。
すでに指摘したように、BEGINセクションでは入力が読み込まれていません。最初の入力行を確認してstdinに番号を指定すると、コードを期待どおりに実行できます。
echo 10 | awk 'NR==1{
num=$1;
if (num%2==0)
printf "%d is Even number.\n",num;
else printf "%d is odd Number.\n",num
}'
10 is Even number.
通常のAwkは、GNU gawk
固有の動作、パイプ、またはリダイレクト(<
)、または-v
(変数の割り当て)オプション。
入力引数の処理、ARGC
(引数 count 、整数)、およびARGV
(引数 vector、「リスト」の別の単語)はすべて the manual で詳細に説明されています。
Mosvyは、背景を説明し、ARGV
を解析するために何を実行する必要があるかを要約した素晴らしい仕事をしました。これは、macOSとGNU/Linuxの両方でテストされた、スタンドアロンのシェルスクリプトとして実装された元の目的です。
simple_if.awk
#!/usr/bin/awk -f
##
## simple_if - tell user if a number given as an argument is even or odd
##
## Example: ./simple_if.awk 11
##
BEGIN {
num = ARGV[1];
# if you expect to arguments AND read from one or more input files, you need
# to remove the arguments from ARGV so Awk doesn't attempt to open them as
# files (causing an error)
#ARGV[1] = "";
if (num % 2 == 0) {
printf "%d is an even number.\n", num;
} else {
printf "%d is an odd number.\n", num;
}
}
このようなAwkスクリプトを作成します 実行可能 with chmod a+x scriptname.awk
、それを$PATH
に入れます。他のBash、Python、Perlスクリプト、Cプログラムなどと同様に実行できます。
システムの他の場所にawk
が存在する場合は、#!
行を適切に更新してください。 awk
must にはスクリプトを実行するための/usr/bin/env
オプションがあり、… であるため、-f
を使用できない場合があります。複雑です 。
.awk
拡張子は必要ありませんまったくですが、エディターが適切な構文強調表示を有効にするのに役立つ場合があります。オフのままにしておくと、Awkスクリプトであることを誰も知る必要はありません。
以下は、有用な処理を行い、妥当なエラー処理を行う、より完全な例です。
simple_stats.awk
#!/usr/bin/awk -f
##
## simple_stats - do simple 1-variable statistics (min/max/sum/average) on
## the first column of its input file(s)
##
## examples: ./simple_stats min numbers.txt
## ./simple_stats all numbers.txt # all stats
## ./simple_stats sum <(du MyFiles) # Bash proc. substitution
##
## # specify '-' as the filename when reading from stdin
## seq 1 100 | ./simple_stats avg -
##
BEGIN {
# expect stats operation as the first argument
op = ARGV[1]
# unset this array index so Awk doesn't try opening it as a file later
# ref: https://www.gnu.org/software/gawk/manual/html_node/ARGC-and-ARGV.html
ARGV[1] = ""
# if you wanted to process multiple command line arguments here, you could
# loop over ARGV, using something like
# for (i=0; i<ARGC; i++) { if (ARGV[i] == "...") { ... } }
if (op !~ /^(min|max|sum|avg|all)$/) {
print "ERROR: Expected one of min/max/sum/avg/all." >"/dev/stderr"
# 'exit' in BEGIN will always run the EXIT block, if one exists
# see https://www.gnu.org/software/gawk/manual/html_node/Assert-Function.html
_assert_exit = 1
exit 1
}
# ordinarily Awk reads stdin without specifying; here, '-' seems necessary
if (ARGV[2] == "") {
print "ERROR: Need an input file (or '-' for stdin)." >"/dev/stderr"
_assert_exit = 1
exit 1
}
}
# 'min' needs an initial value so take the first record
NR == 1 { min = $1 }
# for every input line (including the first)...
{
sum += $1
if ($1 > max) max = $1
if ($1 < min) min = $1
}
END {
if (_assert_exit) exit 1; # if 'exit' was pending from BEGIN block
if (op == "min" || op == "all")
printf "The minimum is: %15d\n", min
if (op == "max" || op == "all")
printf "The maximum is: %15d\n", max
if (op == "sum" || op == "all")
printf "The sum is: %15d\n", sum
if (op == "avg" || op == "all")
printf "The average is: %15.2f\n", sum/NR
}