다음 장난감 예를 고려하십시오.
this is a line
this line contains FOO
this line is not blank
This line also contains FOO
Some random text
This line contains FOO too
Not blank
Also not blank
More random text
FOO!
Yet more random text
FOO!
따라서 FOO에 대한 grep 결과를 원하지만 약간의 추가 문제가 있습니다. 즉, 비어 있지 않고 FOO를 포함하지 않는 한 일치하는 줄을 따르는 줄을 포함해야 한다는 것입니다. 따라서 일치 항목은 서로 다른 일치 항목이 구분되어 다음과 같이 표시됩니다.
게임 1
this line contains FOO
this line is not blank
게임 2
This line also contains FOO
게임 3
This line contains FOO too
Not blank
Also not blank
게임 4
FOO!
Yet more random text
게임 5
FOO!
명령줄에서 실행할 수 있는 간단한 한 줄 스크립트에 대한 보너스 포인트입니다(은유적으로 말하면).
부록: 게임 번호에 실행 횟수를 추가하는 것은 그리 어렵지 않다면 매우 편리할 것입니다.
답변1
awk
대신 사용하십시오 grep
:
awk '/FOO/ { if (matching) printf("\n"); matching = 1 }
/^$/ { if (matching) printf("\n"); matching = 0 }
matching' file
일치하는 버전을 열거합니다.
awk 'function flush_print_maybe() {
if (matching) printf("Match %d\n%s\n\n", ++n, buf)
buf = ""
}
/FOO/ { flush_print_maybe(); matching = 1 }
/^$/ { flush_print_maybe(); matching = 0 }
matching { buf = (buf == "" ? $0 : buf ORS $0) }
END { flush_print_maybe() }' file
두 awk
프로그램 모두 매우 간단한 "상태 머신"을 사용하여 현재 일치하는 항목이 있는지 확인합니다. 패턴이 일치하면 상태 FOO
가 되고 matching
, 패턴 ^$
(빈 줄)이 일치하면 상태가 아닌 상태가 됩니다 matching
.
상태 전환 시 일치하는 데이터 세트 간의 빈 출력 줄이 발생합니다.~에서 matching
(입력하거나 matching
입력하지 않음 matching
).
첫 번째 프로그램은 matching
이 상태에 있는 동안 모든 행을 인쇄합니다.
두 번째 프로그램은 buf
특정 상태의 변수에 있는 행을 수집합니다 matching
. 인쇄한 후(상태에 따라) Match N
비우고 상태 전환 시 레이블 도 비웁니다 (첫 번째 프로그램이 빈 줄을 출력할 때).
샘플 데이터에 대한 마지막 프로그램의 출력은 다음과 같습니다.
Match 1
this line contains FOO
this line is not blank
Match 2
This line also contains FOO
Match 3
This line contains FOO too
Not blank
Also not blank
Match 4
FOO!
Yet more random text
Match 5
FOO!
답변2
sed -ne '/FOO/{x;P;x};/FOO/,/^$/p' testfile
출력에서 공백이 아닌 각 행 블록은 입력에서 일치하는 데이터의 단일 블록입니다. 개행 문자의 수는 다양합니다.
이것
- 출력을 억제합니다(
-n
). - "FOO"가 나타날 때마다 빈 줄을 인쇄합니다(
/FOO/{x;P;x}
- 빈 예약 공간 사용). - FOO( )를 포함하는 줄로 시작하고
/FOO/
빈 줄( )로 끝나는 줄 범위를 선택합니다/^$/
. - 다음 줄(
p
)을 인쇄하세요.
this line contains FOO
this line is not blank
This line also contains FOO
This line contains FOO too
Not blank
Also not blank
FOO!
Yet more random text
FOO!
답변3
AWK에서는 이것이 가능하지 않다고 생각 grep
하지만 AWK에서는 가능합니다.
#! /usr/bin/awk -f
/FOO/ {
matched = 1
if (notfirst) print ""
notfirst = 1
}
/^$/ {
matched = 0
}
matched
일치 횟수:
#! /usr/bin/awk -f
/FOO/ {
matched = 1
if (matches) print ""
printf "Match %d\n", ++matches
}
/^$/ {
matched = 0
}
matched
두 경우 모두 처음 두 블록은 현재 레코드를 출력에 복사해야 하는지 여부를 결정합니다. 현재 레코드가 "FOO"와 일치하면 첫 번째 블록은 matched
1로 설정되고 필요한 경우 빈 레코드가 출력됩니다(두 번째 변형에서 출력될 내용을 분리하기 위해) matches
. 그리고 출력 헤더. 현재 레코드가 비어 있으면 두 번째 블록은 0으로 설정됩니다. 1인 경우 matched
독방 matched
조건은 현재 레코드를 인쇄합니다.matched
답변4
awk '/FOO/{print "===match " ++i "==="} /FOO/,/^$/' file
===match 1===
this line contains FOO
this line is not blank
===match 2===
This line also contains FOO
===match 3===
This line contains FOO too
Not blank
Also not blank
===match 4===
FOO!
Yet more random text
===match 5===
FOO!
유사한 변형을 FOO
다른 것으로 쉽게 변경할 수 있습니다.
awk -vpat=FOO '$0~pat{print "===match " ++i "==="} $0~pat,/^$/' file
기본 인쇄에서 빈 줄을 생략하는 것은 독자의 연습 문제로 남겨집니다 ;-)