awkでシェル変数を使用する


8

これが私のスクリプトです(指定されたパターンを含むファイルを見つけるため):

find . -type f \
    -exec awk -v vawk="$1" '/'"$vawk"'/ {c++} c>0 { print ARGV[1]; exit 0 } END { if (! c) {exit 1}}' \{\} \;

引数付きのスクリプトを使用したい§:

MyScript.sh pattern

私の問題は、$1変数をに入れることができないことawkです。

スクリプトをデバッグしようとすると

bash -x MyScript.sh pattern

これが出力です:

+ find . -type f -exec awk -v vawk=pattern '// {c++} c>0 {print ARGV[1] ; exit 0 } END { if (! c) {exit 1}}' '{}' ';'

$vawk変数が空であるように思われます。

何か案が?

回答:


7

awk変数とシェル変数を混同しているようです。 awk -v vawk="$1"というawk変数が作成されvawkますが、シェル構文($vawk)を使用しようとしています。シェルにはという変数がないため、これは機能しませんvawk。あなたが欲しいのは

awk -v vawk="$1" '$0 ~ vawk { c++ } # ...'
#                      ^ awk variable syntax

1
awkC-などにエスケープシーケンスを展開する$1場合のアプローチは仕事をしないように、$1バックスラッシュ文字(正規表現のための一般的な)を含むことができます。ENVIRON代わりにawk特殊配列を使用できます。
ステファンChazelas

6

再生された今のように閉じられ、この重複質問、それは1が有用見つけるかもしれないawkの変数の受け渡しの制限に関する警告が含まれて。

シェル変数はシェル変数です。これをawk変数に変換する場合は、次のような構文が必要です。

awk -v x="$x" '$2 == x {print $1}' infile

または

awk '$2 == x {print $1}' x="$x" infile

ただし、それらには問題があります。エスケープシーケンスが拡張されます(GNU awk4.2以降では、で$x始まり、@/で終わる場合/、正規表現型の変数として扱われます)。

したがって、たとえば、シェル変数に2つの文字のバックスラッシュnが含まれている場合、awk変数には改行文字が含まれます(gawk 4.2以降では@/foo/、が含まれている場合、awk変数にはが含まれfoo、の型になりますregexp)。

別のアプローチ(ただし、Solaris -vのように1970年代のawkがまだ見つかるのとは対照的に)にはPOSIX awkまたはnawkが必要です/bin/awk)には、環境変数を使用します。

x="$x" awk '$2 == ENVIRON["x"] {print $1}' infile

(まだ新しいawksを使用する)別のアプローチは、awkでARGV配列を使用することです。

awk 'BEGIN {x = ARGV[1]; delete ARGV[1]}
  $2 == x {print $1}' "$x" infile
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.