単語配列でgrepコマンドを使用する

単語配列でgrepコマンドを使用する

いくつかの行を含むテキストファイルがあり、次を使用してテキストファイルを配列に保存しています。

readarray -t array < Textfile

テキストファイルには次の内容が含まれています。

123
456
789

grepコマンドを使用して配列を使用する別のテキストファイルで結果を検索しようとしているので、「123」、「456」、または「789」が表示される行を印刷します。配列をテストするために、grepの同じテキストファイルで「123」、「456」、および「789」を見つけて、3文字のシリーズのうちの1つ以上が発生した場合に一致する行を出力してみました。

頑張った

grep "${array[*]}" Textfile

しかし、これは何の結果も示していません。私は何が間違っていましたか?

答え1

まず、ファイル自体を使用できます。これはシェル配列を使用するよりもはるかに簡単です。

grep -f file1.txt file2.txt

file2.txtこれにより、すべての行に一致するすべての行が印刷されますfile1.txt

もしあなたなら持つ何らかの理由で配列を使用すると、状況がより複雑になります。配列内のスペースで区切られた要素のリストに展開されるため、grep "${array[*]}" Textfileこれを行うことはできません。"${array[*]}"

$ array=("foo" "bar" "baz")
$ echo "${array[*]}"
foo bar baz

これは、あなたのgrepコマンドが次のようになることを意味します。

grep 'foo bar baz' file

foo bar bazこれは「ファイルから検索file」を意味します。あなたがしたいのはgrepですfooまたは barまたは bazgrep-Eオプションを使用して検索したいパターンを追加するだけです|

grep -E 'foo|bar|baz' file

これを行うには、次のような複雑なタスクを実行する必要があります。

grep -E "$(printf '%s|' "${array[@]}" | sed 's/|$//')" file

おそらく:

grep -E "$(export IFS="|"; echo "${array[*]}")" file

全体的にファイルを使用し、配列を忘れた方が良い、高速、簡単です。

答え2

grep "${array[*]}" Textfile

IFSnewline(またはnewlineで始まるすべて)に設定し、最初の要素がnewlineで始まっても機能し続けるかどうかを確認する限り、これは機能します---e-

"${array[*]}"POSIXシェルと同様に、Korn様シェルは、最初の文字に関連付けられた要素の"$*"リストに展開されます$IFS$IFSデフォルトは<SPC><TAB><NL><SPC><TAB><NL><NUL>in zsh)なので、デフォルトではSPC文字を使用して要素を連結します。の場合、各正規表現を順番に繰り返すにgrepは、複数の正規表現を改行で区切る必要があります。grep

IFS=$'\n'
grep -e "${array[*]}" file

では、(グローバル修正の代わりに明示的に改行文字を使用する)または(/ styleで配列を拡張して複数のモードを提供する別の方法になります)をzsh実行する方がきちんとなります。grep -e "${(pj:\n:)array}" filej$IFSgrep -e$^array filefishrcgrep -efirst -esecond filegrep

別のオプションは、次のことです。

printf '%s\n' "${array[@]}" | grep -f - file

grep今回は、改行で区切られたパターンのリストが引数の代わりにstdinを介して渡されます。

-Fこれらの方法は、パターンが固定文字列(using)、拡張正規表現(using -E)、またはデフォルトの正規表現(デフォルト)かどうかに関係なく機能します。

パターンリストが空でないことを確認する必要があるかもしれません。

(( ${#array[@]} > 0 )) && grep ...

grepgrepヌルモードで呼び出すと、実装によって異なる結果が生成され、通常は望む結果ではありません。

関連情報