awk를 사용하여 일치하는 정규식 패턴을 인쇄하는 방법은 무엇입니까?


109

를 사용 awk하여 정규식 패턴과 일치하는 파일에서 단어를 찾아야합니다.

나는 단지 패턴과 일치하는 단어를 인쇄 할.

따라서 줄에 있으면 다음이 있습니다.

xxx yyy zzz

그리고 패턴 :

/yyy/

나는 오직 얻고 싶다 :

yyy

편집 : kurumi 덕분에 나는 다음과 같이 쓸 수있었습니다.

awk '{
        for(i=1; i<=NF; i++) {
                tmp=match($i, /[0-9]..?.?[^A-Za-z0-9]/)
                if(tmp) {
                        print $i
                }
        }
}' $1

그리고 이것은 내가 필요한 것입니다 :) 정말 감사합니다!


1
@maxtaldykin 질문에서 자체 답변을 별도의 답변으로 옮겨 주시겠습니까?
kenorb

2
할 필요가 없습니다 . "정규식과 일치"를 의미 하기 때문에 tmp=match($i, /regexp);if(tmp){}할 수 있어야합니다 . if(tmp ~ $i){}~
JustinCB

답변:


148

이것은 아주 기본적인

awk '/pattern/{ print $0 }' file

awkpattern사용하여 검색 하도록 요청한 //다음 기본적으로 $ 0로 표시되는 레코드라고하는 행을 인쇄하십시오. 적어도 문서를 읽으십시오 .

일치하는 단어 만 인쇄하려는 경우.

awk '{for(i=1;i<=NF;i++){ if($i=="yyy"){print $i} } }' file

49
print기본 작업 이므로 awk '/pattern/' file충분합니다.
Johnsyweb 2011-04-04

18
@Johnsyweb, 네,이 사실을 압니다. marverix와 같은 초보자에게는 더 시각적 인 것을 의미합니다.
kurumi 2011

21
나는 당신의 지식을 의심하지 않습니다. 그러나이 정보는이 답변을 찾는 다른 사람들에게 유용 할 수 있습니다.
Johnsyweb

2
주의 : @marverix는 for(a) "yyy"가 직선 문자열이 아닌 정규식이고 (b) "yyy"가 전체 필드와 일치하지 않는 경우 -loop가 작동하도록 하기 위해 약간의 숙제를해야합니다. 기록.
Johnsyweb

8
그렇지 않을 것입니다 $i=="yyy"; $i ~ /yyy/정규 표현식을위한 것 입니다.
JustinCB

118

GNU의 grep -o동작 을 모방하려는 것 같습니다 . 이렇게하면 각 줄에서 첫 번째 일치 만 원하면됩니다.

awk 'match($0, /regex/) {
    print substr($0, RSTART, RLENGTH)
}
' file

다음은 GNU의 awk구현 () :

awk 'match($0, /a.t/) {
    print substr($0, RSTART, RLENGTH)
}
' /usr/share/dict/words | head
act
act
act
act
aft
ant
apt
art
art
art

에 대한 읽기 match, substr, RSTARTRLENGTH에서 awk수동.

그 후에 같은 줄에서 여러 일치 항목을 처리하기 위해이를 확장 할 수 있습니다.


NB : 마지막 부분에 대답하기 위해 필요한 모든 구성은 kurumi의 대답 과 저의 대답에 있습니다.
Johnsyweb 2011

좋은 대답입니다. 게으 르기 때문에 여기에 설명이 필요합니다. 하지만 이것이 제가 AWK를 사용하는 이유입니다!
lukas.pukenis

인쇄하는 것 외에 매치 결과로 무언가를하고 싶다면 어떻게해야합니까? 예를 들어, 모든 일치 항목을 배열에 추가하고 싶습니다.
Evya2005

@ evya2005 : Ron print 호출을 필요한 할당으로 간단히 바꿀 수 있습니다.
Johnsyweb

그것은 나를 위해 작동하지 않습니다. 인쇄 작업 만. 예를 보여줄 수 있습니까?
Evya2005 2017-06-04

36

gawk 는 이것을 액션으로 사용하여 모든 라인의 일치하는 부분을 얻을 수 있습니다.

{ if (match($0,/your regexp/,m)) print m[0] }

match (string, regexp [, array]) array가 있으면 지워지고 array의 0 번째 요소가 regexp와 일치하는 문자열의 전체 부분으로 설정됩니다. regexp에 괄호가 포함 된 경우 배열의 정수 인덱싱 요소는 해당 괄호로 묶인 하위 표현식과 일치하는 문자열 부분을 포함하도록 설정됩니다. http://www.gnu.org/software/gawk/manual/gawk.html#String-Functions


13

입력의 마지막 줄에만 관심이 있고 일치 항목을 하나만 찾을 것으로 예상하는 경우 (예 : 쉘 명령의 요약 줄의 일부), 정규 표현식 일치를 인쇄하는 방법 에서 채택한이 매우 간단한 코드를 사용해 볼 수도 있습니다. `awk`를 사용합니까? :

$ echo "xxx yyy zzz" | awk '{match($0,"yyy",a)}END{print a[0]}'
yyy

또는 부분적인 결과가있는 더 복잡한 버전 :

$ echo "xxx=a yyy=b zzz=c" | awk '{match($0,"yyy=([^ ]+)",a)}END{print a[1]}'
b

경고 : awk match()세 개의 인수가 있는 함수는에만 존재하고 gawk에는 존재 하지 않습니다.mawk

대신 에서 lookbehind regex 를 사용하는 또 다른 좋은 솔루션 grepawk있습니다. 이 솔루션은 설치 요구 사항이 낮습니다.

$ echo "xxx=a yyy=b zzz=c" | grep -Po '(?<=yyy=)[^ ]+'
b

"tail -n1"을 추가 한 이유는 무엇입니까? 이것 없이는 잘 작동합니다.
Arthur Accioly

1
@ArthurAccioly 맞습니다. 이 용어를 사용하여 핑 호출에서 평균 왕복 시간을 추출했습니다. 그것을 발견 4 년이 걸린 것을 재미)
다니엘 알더

12

Perl이 옵션 인 경우 다음을 시도 할 수 있습니다.

perl -lne 'print $1 if /(regex)/' file

대소 문자를 구분하지 않는 일치를 구현하려면 i수정자를 추가하십시오.

perl -lne 'print $1 if /(regex)/i' file

경기 후 모든 것을 인쇄하려면 :

perl -lne 'if ($found){print} else{if (/regex(.*)/){print $1; $found++}}' textfile

경기와 경기 이후의 모든 것을 인쇄하려면 :

perl -lne 'if ($found){print} else{if (/(regex.*)/){print $1; $found++}}' textfile

3

이 상황에서 sed를 사용하는 것도 우아 할 수 있습니다. 예 (줄에서 일치하는 그룹 "yyy"로 줄 바꾸기) :

$ cat testfile
xxx yyy zzz
yyy xxx zzz
$ cat testfile | sed -r 's#^.*(yyy).*$#\1#g'
yyy
yyy

관련 매뉴얼 페이지 : https://www.gnu.org/software/sed/manual/sed.html#Back_002dreferences-and-Subexpressions


: 나오지도 않은 GNU에 대한 솔루션은이 같은 것입니다sed -n 's/^.*\(yyy\).*$/\1/gp' < testfile
그리고 리 Entin

1
@GrigoryEntin-bsd sed는 원래 답변으로 잘 작동합니다. POSIX에서 지원하는 확장 정규식 스위치는 -E이지만 FreeBSD에서 최소한 -r은 -E와 동일합니다 (2010 년에 추가 된 -r). 어쨌든, -E로 시도해보세요 (gnu sed는 4.3에서 -E를 추가했습니다)
Juan

3

주제에서 벗어난 것은 grep을 사용하여 수행 할 수 있습니다. 누군가가 grep 솔루션을 찾고 있다면 여기에 게시하십시오.

echo 'xxx yyy zzze ' | grep -oE 'yyy'

정규식으로도 잡는 간단한 방법. 정확히 내가 필요한 것. 감사!
Marquee

이것은 나를 위해 작동합니다. 제 경우는 다음과 같습니다. echo "web_port = 8080, shutdown_port = 8005"| grep -oE "web_port = [0-9] +"# return 8080
Robb Tsang

0

찾고있는 텍스트 / 패턴 (예 : "yyy")이 어떤 열에 있는지 알고 있다면 해당 열이 일치하는지 확인하고 인쇄 할 수 있습니다.

예를 들어, 다음 내용이있는 파일 ( asdf.txt 라고 )이 주어집니다.

xxx yyy zzz

두 번째 열이 "yyy"패턴과 일치하는 경우에만 인쇄하려면 다음과 같이 할 수 있습니다.

awk '$2 ~ /yyy/ {print $2}' asdf.txt

이것은 기본적으로 다음과 같이 두 번째 열에 "yyy"가있는 모든 행과 일치합니다.

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