it-swarm-ko.tech

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에게 정규식에서 그룹화 (또는 특정 그룹화)와 일치하는 항목 만 출력하도록 지시하는 방법이 있습니까?

338
Cory Klein

표준 grep은이 작업을 수행 할 수 없지만 최근 버전 GNU grep can . sed, awk 또는 Perl로 설정할 수 있습니다. 샘플 입력을 원할 경우 코너 경우에서 약간 다르게 동작합니다.

foobar Word other stuff by Word, 교체가 완료된 경우에만 인쇄하십시오.

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
46
jgshawkey

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

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

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

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

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

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

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

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

산출:

1

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

9
Thor

grep를 사용하는 것은 -P/--Perl-regexpBSD grep 이 아니라 GNU grep 에서만 사용할 수 있습니다.

ripgrep 를 사용하는 솔루션은 다음과 같습니다.

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

man rg :

-r/--replace REPLACEMENT_TEXT 모든 일치 항목을 제공된 텍스트로 바꿉니다.

그룹 색인 캡처 (예 : $5) 및 이름 (예 : $foo)는 대체 문자열에서 지원됩니다.

관련 : GH-462 .

7
kenorb

@jgshawkey의 답변이 매우 유용하다는 것을 알았습니다. grep는 이것에 대한 좋은 도구는 아니지만 sed는 grep을 사용하여 관련 행을 가져 오는 예가 있지만 여기에는 sed가 있습니다.

Sed의 정규식 구문은 익숙하지 않으면 특이합니다.

여기 또 다른 예가 있습니다 : 이것은 xinput의 출력을 분석하여 ID 정수를 얻습니다.

⎜   ↳ SynPS/2 Synaptics TouchPad                id=19   [slave  pointer  (2)]

나는 19를 원한다

export TouchPadID=$(xinput | grep 'TouchPad' | sed  -n "s/^.*id=\([[:digit:]]\+\).*$/\1/p")

클래스 구문에 유의하십시오.

[[:digit:]]

다음 +

한 줄만 일치한다고 가정합니다.

2
Tim Richardson