awkからエッジ値を取得するより良い方法

awkからエッジ値を取得するより良い方法

いくつかの情報を収集してテーブルに出力することが主な目的であるスクリプトがあります。主な部分はawkスクリプトです:

awk '
    { 
      # do some stuff, including calculating dwt
      printf(format, a, b, c, d)
    }
    END {
      # pass on dwt
    }
' inputfile

awkの主な目的は、テーブルを作成して表示することです。しかし、これはまた、基本スクリプトの他の場所で必要な追加値を計算し、dwtテーブル出力を中断することなくそれらを渡すための最良の方法を見つけることを試みています。

私はこれを行う2つの方法を知っています。

  1. 値を一時ファイルに保存し、END { print dwt > "tempfile" }外部から読み込みますread dwt <tempfile; rm -f tempfile。しかし、既存のファイルが破損しないように、ここに示されているものよりも注意を払っても、私はまだこれを避けることを好みます。他に何もない場合は、ジョブが間違った時間に中断されたため、一時ファイルが残っていることは望ましくありません。
  2. また、値を標準出力に送信しますが、タグ付けされます。 stdout を次のルーチンにパイプして、タグ付き出力を適切にキャプチャして指示しますが、残りは送信します。
    awk '
       ...
        END { 
           print "dwt:" dwt 
        }
     ' inputfile | while read line; do
        if [[ $line = dwt:* ]]; then
           dwt="${line#dwt:}"
        else
           echo "$line"
        fi
     done

しかし、これは人為的でエレガントではないようです。

誰かがより良い方法を知っているのだろうか。別のファイル記述子を試してみましたが、これまでは成功しませんでした。ファイル記述子から情報を取得し、標準出力を損なうことなくdwt環境変数に入れる方法が見つかりませんでした。

答え1

以下は技術です。

  • ENDのstdoutにdwtを印刷します。
  • awk出力を配列として取り込む
  • シェルプロセスで、配列の最後の要素を変数として抽出します。
  • 残りの配列を印刷します。
$ seq 5 > inputfile
$ readarray -t output < <(
    awk '
        { print "table", $0; dwt += $1 }
        END {print dwt}
    ' inputfile
)
$ dwt=${output[-1]}
$ echo "dwt = $dwt"
dwt = 15
$ unset output[-1]
$ printf "%s\n" "${output[@]}"
table 1
table 2
table 3
table 4
table 5

さて、kshがなければ、readarrayシェルスクリプトは次のようになります。

awk '
    { 
      # do some stuff, including calculating dwt
      printf(format, a, b, c, d)
    }
    END {
      # pass on dwt
      print dwt
    }
' inputfile  |&
# ...........^^

typeset -a output
while IFS= read -r -p line; do output+=( "$line" ); done
# .................^^

dwt=${output[-1]}
unset output[-1]
printf "%s\n" "${output[@]}"

# do stuff with $dwt ...

私のksh93のマニュアルページから:

このシンボルは、|&古いパイプを非同期的に実行し、親シェルと双方向パイプを設定します。結果パイプの標準入力と出力は、説明されている組み込み-p コマンドのオプションを使用して親シェルで書き込みおよび読み取ることができます。 read後で。print

答え2

少し不器用ですが、awk評価時にシェルコマンドを印刷できますksh

eval $( echo -e 1\\nA\\n2\\n3\\n4 |
  awk  'NR == 1 {printf"%s%s%s;","export var1=",$0, "\n"}
        NR > 2 {printf"%s%s%s;","echo -e '", $0 , "'\n" }'
)

出力:

2
3
4

$ echo $var1
1

ただし、行ごとのシェル評価は最も簡単ではない可能性があり、特定の文字列の場合、エコーは興味深い結果を提供できます。これらの危険を認識してください!しかし、ハード参照は、以下を避ける必要があります。

eval $( echo -e 1\\nA\\n2\\n3\\n4 |
  awk  'NR == 1 {printf"%s%s%s;","export var1=",$0, "\n"}
        NR > 2 {printf"%s%s%s;","echo -e \x27", $0 , "\x27\n" }'
)

関連情報