web-dev-qa-db-ja.com

システムコマンドの出力を変数に割り当てる

Awkスクリプトでsystemコマンドを実行し、その出力を変数に保存したい。私はこれをやろうとしていましたが、コマンドの出力は常にシェルに送られ、キャプチャすることはできません。これをどのように行うことができるかについてのアイデアはありますか?

例:

$ date | awk --field-separator=! {$1 = system("strip $1"); /*more processing*/}

stripシステムコマンドを呼び出し、出力をシェルに送信する代わりに、出力を$1に割り当ててさらに処理する必要があります。今、それはシェルに出力を送信し、コマンドのretcodeを$1に割り当てています。

45
Sahas

考え出した。

Awkの Two-way I/O を使用します

{
  "strip $1" |& getline $1
}

stripに$ 1を渡し、getlineはstripからの出力を$ 1に戻します

28
Sahas

注:コプロセスはGNU awk固有です。とにかく別の代替方法はgetl​​ineを使用することです

_cmd = "strip "$1
while ( ( cmd | getline result ) > 0 ) {
  print  result
} 
close(cmd)
_

close(cmd)を呼び出すと、awkが複数の呼び出しの後にこのエラーをスローすることを防ぎます:

致命的:パイプ `… 'を開けません(開いているファイルが多すぎます)

56
ghostdog74

awkでシステムコマンドを実行するには、 system() または _cmd | getline_ を使用できます。

_cmd | getline_を好むのは、変数に値をキャッチできるためです:

_$ awk 'BEGIN {"date" |  getline mydate; close("date"); print "returns", mydate}'
returns Thu Jul 28 10:16:55 CEST 2016
_

より一般的には、コマンドを変数に設定できます。

_awk 'BEGIN {
       cmd = "date -j -f %s"
       cmd | getline mydate
       close(cmd)
     }'
_

複数の結果がある場合は「close()」を使用して「オープンファイルが多すぎる」というエラーが発生しないようにすることが重要です(これをコメントで指摘してくれてありがとう mateuscb )。


system()を使用すると、コマンド出力が自動的に印刷され、キャッチできる値はその戻りコードです。

_$ awk 'BEGIN {d=system("date"); print "returns", d}'
Thu Jul 28 10:16:12 CEST 2016
returns 0
$ awk 'BEGIN {d=system("ls -l asdfasdfasd"); print "returns", d}'
ls: cannot access asdfasdfasd: No such file or directory
returns 2
_
28
fedorqui
gawk '{dt=substr($4,2,11); gsub(/\//," ",dt); "date -d \""dt"\" +%s"|getline ts; print ts}'
6
Ryan Liu

Grep出力を処理する必要がある場合、これを使用できます。

echo "some/path/exex.c:some text" | awk -F: '{ "basename "$1"" |& getline $1; print $1 " ==> " $2}'

オプション-F: awkに:フィールド区切り文字として

"basename "$1""最初のフィールドでシェルコマンドbasenameを実行します

|& getline $1サブストリーム内の前のシェルコマンドの出力を読み取ります

output:
exex.c ==> some text
3
cy8g3n