awkのコマンドラインパラメータ

awkのコマンドラインパラメータ

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 is Even number.

awkでユーザーから価値を得る方法は?

答え1

コマンドラインの末尾に指定された引数は通常、スクリプトが読み取るファイル名awkとして扱われます。awkコマンドラインで変数を設定するには-v variable=valueを使用します。

awk -v num=10 -f script.awk

これにより、numスクリプト内の変数として使用できます。上記の例では、変数の初期値は10です。

ENVIRON["variable"]スクリプトで読み取り環境変数を使用するか(名前付き環境変数の場合variable)、コマンドライン引数を表示することもできます。ここでは正の整数ですARGV[n]n


$1in を使用すると、awk現在のレコードの最初のフィールド値を参照しますが、ブロック内で使用するため、まだファイルBEGINからデータを読み取っていません。

コードの数は算術コンテキストで使用される空の変数なので、ゼロと解釈されます。

答え2

$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評価されます。後ろにすでに処理される前のファイルパラメータ:

$ 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

答え3

user313992が言及した重要な点を指摘したいと思います。回答

awkがコマンドライン引数を無視して後でファイルとして開かないようにするには、それを削除するか空の文字列に設定する必要があります。 ARGV[1]=""。

POSIX awkによると文書、引数は次のとおりです。ただ2つの形式のうちの1つとして解釈されます。

  1. 読み取るファイル
  2. 課題フォーマット:var=val

したがって、指定されたパラメータが既存のファイルではなく割り当て形式ではない場合、ただこのパラメータを読んだ後、awkは失敗します。

BEGIN {
 # this is OK:
 for (i=1; i<ARGC; i++) {
  print "+++ ", ARGV[i]
}

# action blocks will fail, because file reading has started
{
  print $1
}

したがって、存在しないパラメータをファイルとして指定することも可能ですが、そのブロックでARGV操作を実行する前にそのパラメータを削除する必要があることに注意してください。

はい -

#!/bin/awk -f
#
# Bin count using thresholds given at argv. E.g.
# 
#   ./bin_count 0.1 0.01 0.001 0.0001 <./data | sort
#   < 0.000100: 3
#   < 0.001000: 12
#   < 0.010000: 56
#   < 0.100000: 100

BEGIN {
    for (i=1; i<ARGC; i++) counts[ARGV[i]] = 0
    delete ARGV    # <<<<< important
}
{
    $1 = $1 < 0 ? -$1 : $1
    for (bin in counts) {
        if ($1 < bin) { counts[bin]++; }
    }
}
END {
    for (bin in counts) {
        printf("< %f: %d\n", bin, counts[bin])
    }
}

答え4

他のC類似プログラムと同様に、一般的なAwkはGNUgawk固有の動作、パイプ、リダイレクト(<)、または-v(変数割り当て)オプションを使用せずにコマンドライン引数を処理することに問題はありません。

入力パラメータ処理ARGC(パラメータ計算、整数)およびARGV(パラメータベクトル、「リスト」の別の単語)がすべて含まれています。手動

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スクリプトを作成してください。実行可能ファイルを使用するにchmod a+x scriptname.awkは にドロップすると、$PATH他のBash、Python、Perlスクリプト、Cプログラムなどと同様に実行されます。

awkシステムの他の場所に存在する場合は、#!その行を適切に更新してください/usr/bin/envawk 〜しなければならない-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
}

関連情報