grep에서 일치하는 지정된 그룹 만 출력 할 수 있습니까? 있음을 나타냅니다. 내가 할

파일이 있다고 가정 해보십시오.

# file: 'test.txt'
foobar bash 1
bash
foobar happy
foobar

“foobar”뒤에 나오는 단어 만 알고 싶기 때문에이 정규식을 사용할 수 있습니다.

"foobar \(\w\+\)"

괄호는 내가 foobar 바로 뒤에있는 단어에 특별한 관심이 있음을 나타냅니다. 내가 할 때 grep "foobar \(\w\+\)" test.txt, 차라리 그냥 “는 foobar 후 단어”보다, 전체 정규 표현식과 일치하는 전체 라인을 얻을 :

foobar bash 1
foobar happy

해당 명령의 출력이 다음과 같이 보이는 것이 훨씬 좋습니다.

bash
happy

grep에게 그룹화 (또는 특정 그룹화)와 일치하는 항목 만 정규식으로 출력하도록 지시하는 방법이 있습니까?



답변

GNU grep에는 -Pperl 스타일 -o정규식 옵션과 패턴과 일치하는 항목 만 인쇄 하는 옵션이 있습니다. 이것들은 둘러보기 어설 션 ( perlre 맨 페이지의 확장 패턴에 설명되어 있음)을 사용하여 조합하여 grep 패턴의 일부를 목적에 맞는 것으로 판단한 것에서 제거 할 수 있습니다 -o.

$ grep -oP 'foobar \K\w+' test.txt
bash
happy
$

\K의 짧은 형태 (보다 효율적인 양식)입니다 (?<=pattern)당신이 출력 할 텍스트 전에 제로 폭 보이는 숨김 주장으로 사용한다. (?=pattern)출력하려는 ​​텍스트 다음에 폭이 0 인 미리보기 어설 션으로 사용할 수 있습니다.

당신의 말과 일치하기를 원한다면 예를 들어, foobar, 당신은 사용할 수 있습니다 :

$ grep -oP 'foo \K\w+(?= bar)' test.txt

또는 (대칭)

$ grep -oP '(?<=foo )\w+(?= bar)' test.txt

답변

표준 grep은이 작업을 수행 할 수 없지만 최신 버전의 GNU grep 은이 작업을 수행 할 수 있습니다 . sed, awk 또는 perl로 설정할 수 있습니다. 다음은 샘플 입력에서 원하는 것을 수행하는 몇 가지 예입니다. 코너 케이스에서는 약간 다르게 동작합니다.

교체 foobar word other stuffword, 교체가 완료되는 경우에만 인쇄 할 수 있습니다.

sed -n -e 's/^foobar \([[:alnum:]]\+\).*/\1/p'

첫 번째 단어가 foobar인 경우 두 번째 단어를 인쇄하십시오.

awk '$1 == "foobar" {print $2}'

foobar그것이 첫 단어라면 벗기고 그렇지 않으면 줄을 건너 뜁니다. 그런 다음 첫 공백 뒤에있는 모든 것을 제거하고 인쇄하십시오.

perl -lne 's/^foobar\s+// or next; s/\s.*//; print'

답변

    sed -n "s/^.*foobar\s*\(\S*\).*$/\1/p"

-n     suppress printing
s      substitute
^.*    anything before foobar
foobar initial search match
\s*    any white space character (space)
\(     start capture group
\S*    capture any non-white space character (word)
\)     end capture group
.*$    anything after the capture group
\1     substitute everything with the 1st capture group
p      print it

답변

foobar가 항상 첫 단어 또는 줄이라는 것을 알고 있다면 cut을 사용할 수 있습니다. 이렇게 :

grep "foobar" test.file | cut -d" " -f2

답변

PCRE가 지원되지 않으면 grep을 두 번 호출하여 동일한 결과를 얻을 수 있습니다. 예를 들어 foobar 다음에 단어를 얻으려면 다음을 수행하십시오.

<test.txt grep -o 'foobar  *[^ ]*' | grep -o '[^ ]*$'

다음 과 같이 foobar 다음에 임의의 단어로 확장 할 수 있습니다 (가독성을 위해 ERE 사용).

i=1
<test.txt egrep -o 'foobar +([^ ]+ +){'$i'}[^ ]+' | grep -o '[^ ]*$'

산출:

1

인덱스 i는 0부터 시작합니다.


답변

pcregrep-o출력하려는 ​​캡처 그룹을 선택할 수 있는 더 스마트 한 옵션이 있습니다. 예제 파일을 사용하면

$ pcregrep -o1 "foobar (\w+)" test.txt
bash
happy

답변

사용은 grep이후, 크로스 플랫폼 호환되지 않습니다 -P/이 --perl-regexp에서만 사용할 GNUgrep 하지 BSDgrep .

다음을 사용하는 솔루션이 있습니다 ripgrep.

$ rg -o "foobar (\w+)" -r '$1' <test.txt
bash
happy

에 따라 man rg:

-r/ --replace REPLACEMENT_TEXT모든 일치하는 텍스트를 주어진 텍스트로 바꿉니다.

캡처 그룹 인덱스 (예 🙂 $5및 이름 (예 🙂 $foo이 대체 문자열에서 지원됩니다.

관련 : GH-462 .