grepはいくつかのパラメータを見つけましたが、発生順に出力します。

grepはいくつかのパラメータを見つけましたが、発生順に出力します。

出力ファイルの内容をgrepしたいです。たとえばabcd

ファイルは次のようになります。

asdf
ab
hgr
cd
ab
asdsda

今私が次のようにab1つずつgrepするならcd

for i in $@
do
  grep $i file
done

わかりました。

ab
ab
cd

私が望むもの

ab
cd
ab

エレガントな解決策はありますか?

答え1

この結果を得る理由は、ループが最初の反復で発生したすべてのケースを最初に実行して返し、次にループが最初の反復で発生したすべてのgrep ab fileケースを実行して返すためです。abgrep cd filecdfile

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このオプションを追加します。

abcdそして(それで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+grepxawk

関連情報