
$n
AWKでコマンド置換を実行し、AWK表記を使用して代替コマンドのフィールドを参照する方法はありますか?
例えば
find | awk '/txt$/ {nl = $(wc -l $NF); print nl}'
.txt
上記の内容で各ファイルの行数を印刷したいと思います。代わりに、実際には次のような出力を返します。
find | awk '/txt$/ {print}'
質問1:awkでコマンド置換を実行する方法はありますか?
質問2:上記の最初の注文が自動的に失敗し、ファイル名のみを印刷するのはなぜですか?
上記は単なる例であることを参照してください。別の方法で各ファイルの行数を印刷する方法を尋ねることはありません。例えばfor f in $(find -iname \*.txt); do wc -l $f; done
問題は、特にAWKプログラムで命令置換を利用する方法に関する。
答え1
まず、免責事項:出力を解析しないでくださいfind
。 次のコードは、コマンドがAwkの入力フラグメントで機能するようにコマンド置換をAwkスクリプトに統合する方法を説明するためのものです。
到着実際にwc -l
見つかった各ファイルの行数()を数えるにはfind
(これは例のユースケースです)、次のようにします。
find . -type f -name '*txt' -exec wc -l {} +
しかし、あなたが要求した質問に答えるには、次のようにします。
第1四半期
あなたの質問1に答えるには:
Q1:awkでコマンド置換を実行する方法はありますか?
もちろん、次の方法がありますman awk
。
Command | getline [var] 出力を $0 または var (上記のように) および RT にパイプしてコマンドを実行します。
だから(引用を見てください!):
find . | awk '/txt$/{"wc -l <\"" $NF "\"|cut -f1" | getline(nl); print(nl)}'
生成された文字列とそれに応じて実行されるコマンドは次のとおりです。
wc -l <file
印刷を避けるためにwc
。
まあ、私はそのコマンドに必要なファイル「閉じる」を避けました(一部のファイルには安全ですが、技術的には正しくありません)。実際には、次のことを行う必要があります。
find . | awk '/txt$/{
comm="wc -l <\"" $NF "\" | cut -f1"
comm | getline nl;
close (comm);
print nl
}'
これは以前のawkバージョンでも機能します。印刷ドットを使用しないでください。
dotはディレクトリで、wcはそれを使用できないため、コードが失敗します。.
find .
またはポイント値を使用しないでください。
find . | awk '/txt$/ && $NF!="." { comm="wc -l <\"" $NF "\" | cut -f1"
comm | getline nl;
close (comm);
print nl
}'
これを1行のコードに変換することはできますが、見苦しく見えます。
第2四半期
2番目の質問は次のとおりです。
Q2:上記の最初の注文が自動的に失敗し、ファイル名のみが印刷されるのはなぜですか?
awkはシェルコマンドを正しく解析できないためです。コマンドを次のように理解します。
nl = $(wc -l $NF)
nl --> variable
$ --> pointer to a field
wc --> variable (that has zero value here)
- --> minus sign
l --> variable (that has a null string)
$ --> Pointer to a field
NF --> Last field
これはl $NF
nullとtheの接続になります。テキストlasフィールド(ファイル名)私。このタイプのテキストを数値変数に拡張する値は 0 です。
awkの場合は次のようになります。
nl = $( wc -l $NF)
nl = $ ( 0 - 0 )
これは$0
入力の完全な行になり(上記の簡単な検索の場合)、ファイル名のみになります。
したがって、上記の内容はすべてファイル名(技術的にはフル行)のみを印刷します。
答え2
"weak quotes"
代わりに、スクリプト内で'strong quotes'
サブシェル拡張を使用してくださいawk
。しかし、例でそうすることは特に価値のある実装ではありません。また、非常に醜いようです。
$ awk "END { print \"$(echo hello)\"} " < /dev/null
hello