grep은 여러 매개변수를 찾았지만 발생 순서대로 출력합니다.

grep은 여러 매개변수를 찾았지만 발생 순서대로 출력합니다.

출력 파일의 내용을 grep하고 싶습니다. 예를 들어 abcd.

파일은 다음과 같습니다.

asdf
ab
hgr
cd
ab
asdsda

지금 내가 다음과 같이 ab하나씩 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

또는(GNU grep또는 호환이 \|표준 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+일치 하지만 하나 이상의 es와 일치함 )x+grepxawk

관련 정보