出力ファイルの内容をgrepしたいです。たとえばab
、cd
。
ファイルは次のようになります。
asdf
ab
hgr
cd
ab
asdsda
今私が次のようにab
1つずつgrepするならcd
for i in $@
do
grep $i file
done
わかりました。
ab
ab
cd
私が望むもの
ab
cd
ab
エレガントな解決策はありますか?
答え1
この結果を得る理由は、ループが最初の反復で発生したすべてのケースを最初に実行して返し、次にループが最初の反復で発生したすべてのgrep ab file
ケースを実行して返すためです。ab
grep cd file
cd
file
for
ループは必要ありません。この試み:
grep -e "^ab$" -e "^cd$" file
または、-x
オプションを使用して行全体と正確に一致する一致のみを選択します(man grep
、thx〜先行は達成するのが難しい):
grep -x -e "ab" -e "cd" file
出力は次のとおりです。
ab
cd
ab
または(GNUgrep
または互換性が\|
標準BRE演算子ではないと仮定):
grep "^\(ab\|cd\)$" file
GNUと同じsed
:
sed '/^\(ab\|cd\)$/!d' file
答え2
使用:
IFS='
' # to join "$*" with newline
grep -e "$*" < file
grep -- "$patterns"
または、grep -e "$patterns"
の各行は$patterns
検索パターンです(ORed)。 (パターン自体が複数行の場合は、"$@"
この点を念頭に置くことをお勧めします。)
POSIXシェルでは、"$*"
位置引数と$IFS
。
-x
パターンが行内の部分文字列ではなく行と正確に一致するようにするには、x
このオプションを追加します。
ab
cd
そして(それでnone)と一致する行は-x
一度だけ印刷され、これはマルチパスアプローチとの別の違いです。一致するパターンごとに一度印刷するには、次のものを使用できますawk
。
awk '
BEGIN {
for (i = 1; i < ARGC; i++) pattern[ARGV[i]]
ARGC = 1
}
{for (p in pattern) if ($0 ~ p) print}' "$@" < file
ただし、awk
パターンは拡張正規表現(例grep -E
:)であることに注意してください。基本的なgrep
なしで理解される正規表現-E
(たとえば、一致するがx+
1つ以上のesと一致する)x+
grep
x
awk