파이프 문자가있는 패턴으로 여러 패턴을 grep하려면 어떻게합니까?


624

두 파일 중 하나와 일치하는 여러 파일에서 모든 줄을 찾고 싶습니다. 입력하여 찾고있는 패턴을 찾으려고 노력했습니다.

grep (foo|bar) *.txt

그러나 쉘 |은 파이프로 해석하고 bar실행 파일이 아닌 경우 불평 합니다.

동일한 파일 세트에서 여러 패턴을 grep하려면 어떻게해야합니까?



grep 'word1 \ | word2 \ | word3'/ path / to / file
lambodar

답변:


861

먼저, 쉘이 패턴을 확장하지 못하도록 보호해야합니다. 가장 쉬운 방법은 작은 따옴표를 묶는 것입니다. 작은 따옴표는 백 슬래시를 포함하여 그 사이에 어떤 것도 확장하지 못하게합니다. 당신이 할 수없는 유일한 패턴에 작은 따옴표가 있습니다.

grep 'foo*' *.txt

작은 따옴표가 필요한 경우 '\''(끝 문자열 리터럴, 리터럴 따옴표, 열린 문자열 리터럴) 로 쓸 수 있습니다 .

grep 'foo*'\''bar' *.txt

둘째, grep은 패턴에 대해 두 가지 구문을 지원합니다. 이전 버전의 기본 구문 ( 기본 정규 표현식 )은 대체 |연산자 ( )를 지원하지 않지만 일부 버전에는 확장 기능이 있지만 백 슬래시로 작성됩니다.

grep 'foo\|bar' *.txt

이식 가능한 방법은 새로운 구문 인 확장 정규 표현식 을 사용하는 것 입니다. 선택하려면 -E옵션 을 전달해야 grep합니다. Linux에서는 egrep대신 grep -E다른 유형으로 입력 할 수도 있습니다 (다른 유니스에서는 별칭으로 만들 수 있음).

grep -E 'foo|bar' *.txt

여러 패턴 중 하나를 찾고있을 때의 또 다른 가능성은 (분리를 사용하여 복잡한 패턴을 작성하는 것과 달리) 여러 패턴을에 전달하는 것 grep입니다. 각 패턴 앞에 -e옵션 을 붙여서이를 수행 할 수 있습니다 .

grep -e foo -e bar *.txt

18
부수적으로-패턴이 고정 될 때, 당신은 실제로 습관을 가져야한다. fgrep또는 grep -F작은 패턴의 경우 그 차이는 무시할 수 있지만 더 길어질수록 이점이 나타나기 시작한다.
TC1

7
@ TC1 fgrep은 매뉴얼 페이지에 따라 사용되지 않습니다
ramn

18
@ TC1 grep -F실제 성능 이점의 유무 는 grep 구현에 달려 있습니다. 그중 일부는 어쨌든 동일한 알고리즘을 적용하므로 -F패턴을 구문 분석하는 데 걸리는 시간과 검색 시간에는 차이가 없습니다. -F예를 들어 GNU grep은 속도가 빠르지 않습니다 (또한 grep -F멀티 바이트 로케일에서 속도를 늦추는 버그가 있습니다 . 동일한 일정한 패턴 grep이 실제로 훨씬 빠릅니다). 반면에 BusyBox grep은 -F큰 파일 에서 많은 이점을 얻습니다 .
Gilles

4
아마도 정규 표현식 의 일부만 변경 해야하는 복잡한 패턴의 경우 "\ ("및 "\)"로 그룹화 할 수 있습니다 (이스케이프는 기본 "기본 정규 표현식"에 대한 것임). ) (?).
Peter Mortensen

4
그 참고 egrep선행 grep -E. GNU에만 국한된 것은 아닙니다 (확실히 Linux와는 아무런 관련이 없습니다). 실제로, 여전히 기본 grep이 지원하지 않는 Solaris와 같은 시스템을 찾을 수 있습니다 -E.
Stéphane Chazelas

90
egrep "foo|bar" *.txt

또는

grep "foo\|bar" *.txt
grep -E "foo|bar" *.txt

gnu-grep 매뉴얼 페이지를 선택적으로 인용 :

   -E, --extended-regexp
          Interpret PATTERN as an extended regular expression (ERE, see below).  (-E is specified by POSIX.)

Matching Control
   -e PATTERN, --regexp=PATTERN
          Use PATTERN as the pattern.  This can be used to specify multiple search patterns, or to protect  a  pattern
          beginning with a hyphen (-).  (-e is specified by POSIX.)

(...)

   grep understands two different versions of regular expression syntax: basic and extended.”  In  GNU grep,  there
   is  no  difference  in  available  functionality  using  either  syntax.   In  other implementations, basic regular
   expressions are less powerful.  The following description applies to extended regular expressions; differences  for
   basic regular expressions are summarized afterwards.

처음에는 더 이상 읽지 않았으므로 미묘한 차이점을 인식하지 못했습니다.

Basic vs Extended Regular Expressions
   In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead  use  the
   backslashed versions \?, \+, \{, \|, \(, and \).

나는 예제에서 배웠기 때문에 항상 egrep을 사용했고 불필요하게 parens을 사용했습니다. 이제 새로운 것을 배웠습니다. :)


22

TC1이 말했듯 -F이 사용 가능한 옵션 인 것 같습니다.

$> cat text
some text
foo
another text
bar
end of file

$> patterns="foo
bar" 

$> grep -F "${patterns}" text
foo
bar

1
@poige $ 'foo \ nbar'옵션에 대해 몰랐습니다. 확장이 어떻게 작동하는지 잘 모르고 조회해야하지만 고맙습니다. 정말 유용합니다.
haridsv

좋은! 이 옵션은 정규식을 비활성화하기 때문에 훨씬 빠르게 실행되는 것처럼 보입니다.
qwertzguy

15

먼저 특수 문자에 따옴표를 사용해야합니다. 둘째, 그럼에도 불구 grep하고 교대를 직접 이해하지 못합니다. egrep또는 (GNU grep만 사용 ) 을 사용해야 grep -E합니다.

egrep 'foo|bar' *.txt

(대체가 더 큰 정규식의 일부가 아니면 괄호는 필요하지 않습니다.)


4
실제로 grep -E는보다 표준 egrep입니다.
jw013

8

정규식이 필요하지 않은 경우 다음 과 같이 여러 -e 매개 변수 를 사용 fgrep하거나 사용하는 것이 훨씬 빠릅니다 grep -F.

fgrep -efoo -ebar *.txt

fgrep(또는 grep -F)는 정규 표현식 대신 고정 문자열을 검색하기 때문에 일반 grep보다 훨씬 빠릅니다.


4
fgrep더 이상 사용되지 않는 이 페이지의 주석도 참조하십시오 .
phk

6

아래 명령을 사용하여 결과를 얻을 수 있습니다.

egrep 'rose.*lotus|lotus.*rose' some_file

3

여러 패턴을 잡기위한 싸고 쾌활한 방법 :

$ echo "foo" > ewq ; echo "bar" >> ewq ; grep -H -f ewq *.txt ; rm ewq

설명이 도움이 될 수 있습니다.
피터 Mortensen

2
grep의 -f옵션은 여러 패턴을 가진 파일을 가져옵니다. 나중에 삭제하는 것을 잊을 수있는 임시 파일을 만드는 대신 쉘의 프로세스 대체를 사용하십시오.grep -f <(echo foo; echo bar) *.txt
Jakob

3

파이프 ( |)는 특수 쉘 문자이므로 이스케이프 처리 ( \|)하거나 매뉴얼 ( man bash)에 따라 인용 해야합니다 .

인용은 특정 문자 나 단어가 쉘에 특수한 의미를 제거하는 데 사용됩니다 . 특수 문자에 대한 특수 처리를 비활성화하고 예약어가 인식되지 않도록하고 매개 변수 확장을 방지하는 데 사용할 수 있습니다.

큰 따옴표로 문자를 묶으 면 따옴표 안에있는 모든 문자 의 리터럴 값유지 됩니다.

따옴표가없는 백 슬래시 ( \)는 이스케이프 문자입니다.

참조 : Bash에서 어떤 문자를 이스케이프해야합니까?

다음은 몇 가지 예입니다 (아직 언급되지 않은 도구 사용).

  • 사용 ripgrep:

    • rg "foo|bar" *.txt
    • rg -e foo -e bar *.txt
  • 사용 git grep:

    • git grep --no-index -e foo --or -e bar

      참고 : 또한 같은 부울 식을 지원 --and, --or하고 --not.

라인 당 AND 연산은 여러 AND 패턴으로 grep을 실행하는 방법을 참조하십시오.

파일 당 AND 연산은 파일 에 여러 문자열 또는 정규식이 모두 있는지 확인하는 방법을 참조하십시오.


3

날짜가 어리석게 형식화 된 액세스 로그가 있습니다 : [30 / Jun / 2013 : 08 : 00 : 45 +0200]

그러나 나는 그것을 다음과 같이 표시해야했습니다 : 30 / Jun / 2013 08:00:45

문제는 grep 문에서 "OR"을 사용하면 두 개의 별도 줄에 두 개의 일치 표현식이 수신된다는 것입니다.

해결책은 다음과 같습니다.

grep -in myURL_of_interest  *access.log  | \
grep -Eo '(\b[[:digit:]]{2}/[[:upper:]][[:lower:]]{2}/[[:digit:]]{4}|[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}\b)'   \
| paste - - -d" " > MyAccess.log

2

TL; DR : 여러 패턴 중 하나를 일치시킨 후 더 많은 작업을 수행하려면 다음과 같이 묶으십시오. \(pattern1\|pattern2\)

예 : 이름 'date'를 포함하는 변수가 String 또는 int로 정의 된 모든 장소를 찾고 싶습니다. (예 : "int cronDate ="또는 "String textFormattedDateStamp =") :

cat myfile | grep '\(int\|String\) [a-zA-Z_]*date[a-zA-Z_]* =' 

을 사용 grep -E하면 괄호 나 파이프를 벗어날 필요가 없습니다.grep -E '(int|String) [a-zA-Z_]*date[a-zA-Z_]* ='


1

이것은 나를 위해 작동

root@gateway:/home/sshuser# aws ec2 describe-instances --instance-ids i-2db0459d |grep 'STATE\|TAG'

**STATE**   80      stopped

**STATE**REASON     Client.UserInitiatedShutdown    Client.UserInitiatedShutdown: User initiated shutdown

**TAGS**    Name    Magento-Testing root@gateway:/home/sshuser#

1

여러 가지 방법이 있습니다.

  1. grep 'foo\|bar' *.txt
  2. egrep 'foo|bar' *.txt
  3. find . -maxdepth 1 -type f -name "*.txt" | xargs grep 'foo\|bar'
  4. find . -maxdepth 1 -type f -name "*.txt" | xargs egrep 'foo|bar'

세 번째 및 네 번째 옵션은 파일에서만 grep하고 디렉토리 .txt이름에 포함 되지 않도록 합니다.
따라서 사용 사례에 따라 위에서 언급 한 옵션 중 하나를 사용할 수 있습니다.
감사!!


0

탭과 공백을 포함하는 여러 패턴이있는 경우 @geekosaur의 답변 에 추가 하려면 다음 명령을 사용하십시오.

grep -E "foo[[:blank:]]|bar[[:blank:]]"

[[:blank:]]공백 또는 탭 문자를 나타내는 RE 문자 클래스는 어디에 있습니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.