次のスクリプトが保存されておりbin
、定義された変数に基づいて出力を取得するために使用されます。現在、スクリプトは列1に対して実行されており、出力を提供しています。列1または列2と一致するときに出力を提供するようにこのスクリプトをどのように更新できますか?
cat ~/bin/POUT
#!/bin/bash
exec awk -v arg=${1:?} '$1==arg' "${@:2}" inputfile
入力ファイル -:
DEV RETAIL RETAILDEVNode
TEST RETAILTEST RETAILTESTNode
TEST AUDIT AUDITTESTNode
QA AUDITQA AUDITQANode
PROD SALE SALEPRODNode
QA SALEQA SALETESTNode
QA FINANCE FINANCEQANode
PROD FINANCE FINANCEPRODNode
現在予想される結果を得ています -
$ POUT QA
QA AUDITQA AUDITQANode
QA SALEQA SALETESTNode
QA FINANCE FINANCEQANode
また、次のような出力が必要です(列2でも検索)。
$ POUT AUDITQA
QA AUDITQA AUDITQANode
Want output like this also (put any matching value and search in column 2 aslo) ---
$ POUT DITQ
QA AUDITQA AUDITQANode
したがって、変数に入力が何であれ、列1と列2を検索して出力を提供する必要があります。
答え1
#!/bin/bash
arg="${1:?}" # Capture argument value or fail
shift
awk -v arg="${arg//\\/\\\\}" 'index($1, arg) || index($2, arg)' "$@" inputfile
シェル変数を使用するときは常に二重引用符を使用してください。 (例外が発生する理由を理解するまでこれは本当です。それまでは常に二重引用符を使用してください。)
$arg
シェル変数は、バックスラッシュ処理をキャンセルするためにawk
変数をランダムに変数に割り当てます。arg
awk
残りのコマンドライン引数を渡す理由は理解できません。awk
そしてinputfile
継続的なソースとして提供されます。それでも意図した場合に備えて保管しました。
答え2
可能:
#! /bin/sh -
export ARG="${1?}"
shift
exec awk '
BEGIN{
field = 1
arg = ENVIRON["ARG"] ""
}
$field == arg' "$@" inputfile
その後、これを呼び出して、CLI以前のバージョンとの互換性を維持しながら2番目のフィールドをPOUT AUDITQA field=2
確認できます。AUDITQA
いくつかの注意:
- bashまたはshで引用符を拡張することを忘れた場合、
-v arg=${1?}
これはSplit + globの影響を受けます。これは、任意のコマンド実行の脆弱性を引き起こすので、非常に悪いです。これは実際に与えられた例の一つです。bash / POSIXシェルで変数を引用することを忘れてしまうセキュリティリスク -v
任意のテキストを渡すためにマングルバックスラッシュを使用することはできません-v
。したがって、ENVIRON
上記の方法を使用しても問題はありません。awk
引数は変数の代入として扱われるため、foo=bar.txt
ファイル名に文字が含まれている場合。代わり=
に転送する必要があります。./foo=bar.txt
foo=bar.txt
$field
およびENVION["var"]
/または-v
数値として見える渡された変数は、数値文字列として扱われ、==
最終的に文字列比較の代わりに数値比較を実行することができます。常に文字列として処理されるように接続するため、たとえば""
引数を使用して呼び出すと、10.0、010、または1e1と一致しません。ENVIRON["ARG"]
10