파일에서 이것 또는 저것 (2 가지)을 어떻게 grep 할 수 있습니까?


36

"다음"과 "있음"이있는 파일이 있습니다.

저 할 수 있어요

$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some

그리고 나는 할 수있다

$ grep "there " x.x
If there is no blob none some will be created

한 번의 작업으로 두 가지를 모두 검색하려면 어떻게해야합니까? 나는 시도했다

$ grep (then|there) x.x

-bash : 예기치 않은 토큰`( '근처의 구문 오류

grep "(then|there)" x.x
durrantm.../code
# (Nothing)

답변:


51

표현식을 따옴표로 묶어야합니다. 당신이받는 오류는 bash (가 특수 문자로 해석 한 결과입니다 .

또한 grep에게 확장 정규 표현식을 사용하도록 지시해야합니다.

$ grep -E '(then|there)' x.x

확장 정규 표현식이 없다면, 당신은 탈출 할 |, (그리고 ). 여기서는 작은 따옴표를 사용합니다. Bash는 큰 따옴표로 백 슬래시를 특수하게 처리합니다.

$ grep '\(then\|there\)' x.x

이 경우 그룹화가 필요하지 않습니다.

$ grep 'then\|there' x.x

다음과 같은 것이 필요합니다.

$ grep 'the\(n\|re\)' x.x

3
참조 grep $'then\nthere'grep -e then -e there. 참고 \|BREs 표준이 아니다. 나머지는 특별히 큰 따옴표 배쉬 취급 백 슬래시 전에 만 ", $, \ , `뉴 라인.
Stéphane Chazelas

1
의 목적은 x.x무엇입니까?
alex

7

간단한 부록, 대부분의 맛에는 egrep라는 명령이 있으며 -E로 grep됩니다. 나는 개인적으로 타이핑하는 것이 훨씬 더 좋아

egrep "i(Pod|Pad|Phone)" access.log

grep -E를 사용하는 것보다


2

(또는 적어도 내) 매뉴얼 페이지의 REGULAR EXPRESSIONS에 문서화 된 내용은 실제로 확장 정규식에 대한 것입니다.

grep은 "기본", "확장"및 "perl"의 세 가지 정규식 구문 버전을 이해합니다. GNU grep에서는 기본 구문과 확장 구문간에 사용 가능한 기능에 차이가 없습니다. 다른 구현에서는 기본 정규 표현식의 성능이 떨어집니다. 다음 설명은 확장 정규식에 적용됩니다. 기본적인 정규 표현식의 차이점은 나중에 요약됩니다.

그러나 grep은 기본적으로 사용하지 않습니다. -E스위치 가 필요합니다 .

grep "(then|there)" x.x

(Man 페이지에서 다시) :

기본 정규 표현식과 확장 정규 표현식

기본 정규 표현식에서 메타 문자?, +, {, |, (및)는 특별한 의미를 잃습니다. 대신 백 슬래시 버전 \ ?, +, {, \ |, (및)를 사용하십시오.

따라서 다음을 사용할 수도 있습니다.

grep "then\|there" x.x

이 경우 괄호가 불필요하기 때문에.


0

Bash의 우아한 단순함은 거대한 맨 페이지에서 잃어버린 것 같습니다.

위의 우수한 솔루션 외에도 bash가 구문을 구문 분석하고 해석하는 방법대한 치트 시트를 제공하려고 생각했습니다 . 그런 다음이 로드맵을 사용하여 질문자가 제시 한 예제를 구문 분석하여 의도 한대로 작동하지 않는 이유를 더 잘 이해할 수 있도록하겠습니다.


참고 : 셸 스크립트 줄이 직접 사용됩니다. 입력 된 입력 줄이 먼저 기록 확장됩니다.

각 bash 라인은 먼저 토큰 화 되거나, 다시 말해서 tokens 로 잘립니다 . (토큰 화는 중괄호, 물결표, 매개 변수, 명령, 산술, 프로세스, 단어 분할 및 파일 이름 확장을 포함한 다른 모든 확장 전에 발생합니다.)

여기서 토큰은 입력 줄에서이 특수 메타 문자 중 하나로 구분 (구분) 된 부분을 의미합니다.

space,  - White space...
tab, 
newline,

‘<’,    - Redirection & piping...
‘|’, 
‘>’
‘&’,    - And/Both < | > | >>  .or.  &<file descriptor>

‘;’,    - Command termination

‘(’,    - Subshell, closed by -     ‘)’

Bash는 다른 많은 특수 문자를 사용하지만이 10 개만 초기 토큰을 생성합니다.

그러나 이러한 메타 문자도 때때로 토큰 내에서 사용해야하므로 특별한 의미를 빼앗을 방법이 필요합니다. 이를 탈출이라고합니다. (즉, 하나 이상의 문자열을 인용하여 중 하나를 수행 탈출 'xx..', "xx..") 또는 백 슬래시 (즉, 함께 개별 문자를 앞에 붙여 \x). 따옴표도 따옴표로 묶어야하고 큰 따옴표는 모든 것을 따옴표로 묶지 않기 때문에 이보다 조금 더 복잡합니다. 그러나이 단순화는 현재 가능합니다.

bash 인용을 다른 언어와 같이 텍스트 문자열을 인용하는 아이디어와 혼동하지 마십시오. bash에서 따옴표 사이에있는 것은 문자열이 아니라 메타 문자가 이스케이프 된 입력 줄의 섹션이므로 토큰을 구분하지 않습니다.

'", 사이에는 중요한 차이점이 있지만 다른 날입니다.

나머지 이스케이프되지 않은 메타 문자는 토큰 구분 기호가됩니다.

예를 들어

$ echo "x"'y'\g
xyg

$ echo "<"'|'\>
<|>

$ echo x\; echo y
x; echo y

첫 번째 예에서는이 공간 구분에 의해 생산이 토큰은 다음과 같습니다 echoxyz.

두 번째 예에서도 마찬가지입니다.

세미콜론 이스케이프 제 3 실시 예에서, 이렇게 공간 분리에 의해 생성 된 토큰이있다 4 echo, x;, echo, 및 y. 그런 다음 첫 번째 토큰이 명령으로 실행되고 다음 세 개의 토큰이 입력으로 사용됩니다. 두 번째 echo는 실행되지 않습니다.


기억해야 할 중요한 것은 이스케이프 문자 그 bash에 처음 모습이다 ( ', ", 및 \), 다음 순서대로, 이스케이프 메타 문자 구분 기호를 찾습니다.

이스케이프되지 않으면이 10 개의 특수 문자는 token구분 기호로 사용됩니다. 그들 중 일부는 추가 의미가 있지만 무엇보다도 토큰 구분 기호입니다.


grep이 기대하는 것

GREP 위의 예는이 토큰을 필요에, grep, string, filename.

첫 번째 시도는 다음과 같습니다.

$ grep (그럼) xx

이 경우 (, )|이스케이프 메타 문자입니다 그래서 이러한 토큰으로 입력을 분할하는 역할 : grep, (, then, |, there, ),와 x.x. 그렙이보고 싶어 grep, then|there하고 x.x.

질문의 두 번째 시도는 다음과 같습니다.

grep "(그럼)"xx

이것은으로 토큰 화 grep, (then|there), x.x. 에코를 grep으로 바꾸면 다음과 같이 표시됩니다.

echo "(그럼)"xx
(그럼) xx

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