
いくつかの行を含むテキストファイルがあり、次を使用してテキストファイルを配列に保存しています。
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
、または baz
。grep
-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
IFS
newline(または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}" file
j
$IFS
grep -e$^array file
fish
rc
grep -efirst -esecond file
grep
別のオプションは、次のことです。
printf '%s\n' "${array[@]}" | grep -f - file
grep
今回は、改行で区切られたパターンのリストが引数の代わりにstdinを介して渡されます。
-F
これらの方法は、パターンが固定文字列(using)、拡張正規表現(using -E
)、またはデフォルトの正規表現(デフォルト)かどうかに関係なく機能します。
パターンリストが空でないことを確認する必要があるかもしれません。
(( ${#array[@]} > 0 )) && grep ...
grep
grep
ヌルモードで呼び出すと、実装によって異なる結果が生成され、通常は望む結果ではありません。