私のシェル関数の1つに以下を持っています:
function _process () {
awk -v l="$line" '
BEGIN {p=0}
/'"$1"'/ {p=1}
END{ if(p) print l >> "outfile.txt" }
'
}
なので、_process $arg
として呼び出されると、$arg
は$1
として渡され、検索パターンとして使用されます。 Shellはawkパターンの代わりに$1
を展開するため、このように機能します。また、l
は、-v l="$line"
で宣言されているawkプログラム内で使用できます。大丈夫だ。
同じようにパターンを変数として検索することは可能ですか?
以下は動作しません、
awk -v l="$line" -v search="$pattern" '
BEGIN {p=0}
/search/ {p=1}
END{ if(p) print l >> "outfile.txt" }
'
、なぜならawkは/search/
を変数として解釈せず、文字どおりに解釈するからです。
Awkの~
演算子。右側に正規表現のリテラルを指定する必要はありません。
function _process () {
awk -v l="$line" -v pattern="$1" '
$0 ~ pattern {p=1}
END {if(p) print l >> "outfile.txt"}
'
}
これはより効率的ですが(ファイル全体を読み取る必要はありません)
function _process () {
grep -q "$1" && echo "$line"
}
パターンによっては、grep -Eq "$1"
_awk -v pattern="$1" '$0 ~ pattern'
_
awk
がANSI Cのエスケープシーケンス(改行の場合は_\n
_、フォームフィードの場合は_\f
_、バックスラッシュの場合は_\\
_など)を_$1
_で展開するという問題があります。したがって、_$1
_に正規表現で一般的なバックスラッシュ文字が含まれている場合に問題になります(GNU awk
4.2以降、 で始まる値_@/
_および_/
_で終わることも問題です )。この問題の影響を受けない別のアプローチは、次のように記述することです。
_PATTERN=$1 awk '$0 ~ ENVIRON["PATTERN"]'
_
それがどれほど悪くなるかは、awk
の実装に依存します。
_$ nawk -v 'a=\.' 'BEGIN {print a}'
.
$ mawk -v 'a=\.' 'BEGIN {print a}'
\.
$ gawk -v 'a=\.' 'BEGIN {print a}'
gawk: warning: escape sequence `\.' treated as plain `.'
.
$ gawk5.0.1 -v 'a=@/foo/' BEGIN {print a}'
foo
_
すべてのawk
sは、有効なエスケープシーケンスでも同じように機能します。
_$ a='\\-\b' awk 'BEGIN {print ENVIRON["a"]}' | od -tc
0000000 \ \ - \ b \n
0000006
_
(_$a
_の内容はそのまま渡されます)
_$ awk -v a='\\-\b' 'BEGIN {print a}' | od -tc
0000000 \ - \b \n
0000004
_
(_\\
_が_\
_に変更され、_\b
_がバックスペース文字に変更されました)。
次のようなものを試してください:
awk -v l="$line" -v search="$pattern" 'BEGIN {p=0}; { if ( match( $0, search )) {p=1}}; END{ if(p) print l >> "outfile.txt" }'
いいえ、ただし、パターンをawkに渡す二重引用符で囲まれた文字列に単純に補間できます。
awk -v l="$line" "BEGIN {p=0}; /$pattern/ {p=1}; END{ if(p) print l >> \"outfile.txt\" }"
二重引用符で囲まれたawkリテラルをエスケープする必要があることに注意してください。これは、これを実現する最も簡単な方法です。