複数のモードを渡したい、各モードにオプションを適用する方法にはgrep
多くのソリューションがあります。-e
さまざまなモードが配列に保存されますptrn
。配列要素の空白は-e
パターンに個別に渡されないため、誤って解釈される可能性があるかどうか疑問に思います。
可能性は
可能性1
mptrn=$( printf -- ' -e %s' "${ptrn[@]}" )
grep -E "$mptrn" -- "$flnm"
可能性2
for i in "${!ptrn[@]}"; do
ptrn[$i]="-e ${ptrn[$i]}"
done
grep -E "${ptrn[@]}" -- "$flnm"
可能性3
eptrn=()
for i in "${!ptrn[@]}"; do
eptrn+=("-e" "${ptrn[$i]}")
done
grep -E "${eptrn[@]}" -- "$flnm"
どのソリューションでも発生する可能性のある問題は何ですか?
答え1
こうしておいてくださいptrn=(" a b" " 333 22 1 ")
。
答え1:
mptrn=$( printf -- ' -e %s' "${ptrn[@]}" )
grep -E "$mptrn" -- "$flnm"
コマンドの完全な出力はに割り当てられmptrn
、配列の要素に空白文字が含まれていると、使用されている形式によってその要素を区別できません。 (先行および末尾のスペース文字を含む)がmptrn
含まれます。-e a b -e 333 22 1
実行すると、引用grep
符付き引数は先行スペースのためパターン引数として解釈されます。これは達成しよ"$mptrn"
うとするのではなく、指定されたファイルから項目を検索します。このタスクと同じタスクを実行するには、次のものを使用できます。IFS
範囲。
[ "${IFS+x}" = x ] && OLD_IFS=$IFS
IFS=$(printf '\x7f')
mptrn=$(printf "-e${IFS}%s${IFS}" "${ptrn[@]}")
# note that we don't use quotes
grep -E $mptrn -- "$flnm"
if [ "${OLD_IFS+x}" = x ]; then IFS=$OLD_IFS; else unset IFS; fi
答え2:
for i in "${!ptrn[@]}"; do
ptrn[$i]="-e ${ptrn[$i]}"
done
grep -E "${ptrn[@]}" -- "$flnm"
この回答は、検索されたパターンに先行するスペースが含まれることを除いて、所望の結果に近い。つまり、生成されたコマンドは次のようになります。
grep -E "-e a b" "-e 333 22 1 " -- file
スペースを削除すると問題が解決しますptrn[$i]=-e${ptrn[$i]}
。
答え3:
eptrn=()
for i in "${!ptrn[@]}"; do
eptrn+=("-e" "${ptrn[$i]}")
done
grep -E "${eptrn[@]}" -- "$flnm"
この答えは正しいです。生成されたgrep
コマンドは次のとおりです。
grep -E -e " a b" -e " 333 22 1 " -- file
答え2
これを正規表現に結合します。たとえば、任意のパターンと一致させたい場合は、正規表現置換演算子を|
ORとして使用できます。
まず、join_by
bashで関数を作成します。
join_by () {
local d="$1";
shift;
printf '%s' "$1";
shift;
printf '%s' "${@/#/$d}"
}
perl
これは組み込み関数の非常に単純な複製ですjoin
。最初のパラメータを区切り文字として使用し、次に区切り文字を使用して、追加の面倒な先行または末尾の区切りなしで残りのすべてのパラメータを連結します。
次に、次のように使用します。
$ p=(a b c d e)
$ re=$(join_by '|' "${p[@]}")
$ echo $re
a|b|c|d|e
$ reを使用できますgrep -E
(交換するには拡張正規表現「ERE」が必要です)。
grep -E "$re" filename
より複雑なブール演算(たとえばa && b && ! (c || d || e
)を実行する必要がある場合は、perlまたはawkを使用してください。 bashはデータ処理言語には適していません。