これは私のスクリプトです(指定されたパターンを含むファイルを見つけるため)。
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
が空のようです。
どんなアイデアがありますか?
答え1
awk変数とシェル変数を混同しているようです。 awk -v vawk="$1"
作るアッ変数名が指定されましたが、vawk
使用しようとしています。シェル構文($vawk
)。シェルにという変数がないため、機能しませんvawk
。私の考えでは、あなたが望むもの
awk -v vawk="$1" '$0 ~ vawk { c++ } # ...'
# ^ awk variable syntax
答え2
今後今は次のように閉鎖されています。コピー質問これには、awkの変数転送制限に関する警告が含まれているため、便利です。
シェル変数は次のとおりです。ㅏシェル変える。それをアッ変数には次の構文が必要です。
awk -v x="$x" '$2 == x {print $1}' infile
または
awk '$2 == x {print $1}' x="$x" infile
しかし、問題が発生します。エスケープシーケンスが拡張されます。
また、GNU awk
4.2以上の場合、$x
で始まり@/
終わる場合は、/
正規表現型の変数として扱われます。)。
たとえば、シェル変数に2つの文字が含まれている場合バックスラッシュそしてN、awk変数には最終的に次のものが含まれます。新しいチーム文字とgawk 4.2+の場合が含まれている場合、@/foo/
awk変数にはが含まれてfoo
型になりますregexp
。さらに悪いことに、@/(xxxxx){1,20000}/
gawkが数時間またはメモリが不足するまでCPUを占有して正規表現をコンパイルしようとすると、DoSの脆弱性の一種になることがあります。
別の方法(しかし-v
POSIX awkまたはnawkが必要です(Solarisでまだ使用されている1970年代awkとは反対/bin/awk
))は、環境変数を使用することです。
x="$x" awk '$2 == ENVIRON["x"] {print $1}' infile
別の方法(まだ最新のawkを使用)は、awkでARGV配列を使用することです。
awk -- 'BEGIN {x = ARGV[1]; delete ARGV[1]}
$2 == x {print $1}' "$x" infile
また、 //ARGV
または引数を使用しても、対応する文字列は次のように処理されます。ENVIRON
-v
var=value
数値文字列数値型の場合(認識される数値形式の範囲は実装によって異なります)。
上記の例では、orであれば$2 == ENVIRON["VAR"]
文字列比較になりますが、or(または実装とバージョンによって)であれば数値比較になるので重要です。数字です。したがって、とは同じと見なされます。$VAR
foo
1f2
1e2
1.1
inf
0xff
awk
$2
10.0e1
100
1e2
行為:
awk 'BEGIN {var = "" ENVIRON["VAR"]}'
シェル変数が数値のように見えても、var
awk
変数は常に文字列として扱われていることを確認してください。$VAR
awk 'BEGIN {var = 0 + ENVIRON["VAR"]}'
これを数値に変換します(少なくとも前の部分は数値として解釈できます)。
あるいは、strcoll()
いくつかの実装(POSIXで要求されているように)と比較した場合、つまり、どちらか一方または両方が同じソート順を持つ場合、1つa == b
またはa
両方が文字列の場合はb
trueを返します。a
b