패턴과 일치하는 모든 줄을 찾고 그 위의 줄만 인쇄합니다.

패턴과 일치하는 모든 줄을 찾고 그 위의 줄만 인쇄합니다.

문자열을 찾아서 그 위에 있는 줄을 인쇄해야 합니다.

사례 1: 같은 줄에 여러 개의 일치하는 패턴이 없습니다.

즉) 다음을 포함하는 파일을 고려하십시오.

$cat > para
returns between the paragaraphs
italic or bold    
quotes by placing
italic

여기서 이탤릭체를 찾아야 하고 아래와 같이 출력을 얻어야 합니다.

단락 사이로 돌아가기
견적을 내서

어떻게 그런 결과를 얻을 수 있나요?

답변1

일치하는 텍스트의 맥락에서 "패턴"이라는 단어는 매우 모호하므로 사용하지 마십시오. 일치를 참조하는 항목 중 적어도 "문자열" 또는 "정규식" 및 "부분" 또는 "완전"을 항상 사용하십시오. 바라보다https://stackoverflow.com/q/65621325/1745001더 많은 정보를 알고 싶습니다.

귀하의 질문으로는 귀하가 원하는 일치 유형을 알 수 없으므로 다음은 게시된 예제 입력을 기반으로 게시된 예상 출력을 생성하는 몇 가지 예이며, 그 중 일부/모두가 연산자의 요구 사항과 전혀 일치하지 않을 수 있습니다. :

부분 행 정규식 일치:

$ awk '/italic/{print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

부분 행 문자열 일치:

$ awk 'index($0,"italic"){print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

부분 필드 정규식 일치:

$ awk '{for (i=1; i<=NF; i++) if ($i ~ /italic/) print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

부분 필드 문자열 일치:

$ awk '{for (i=1; i<=NF; i++) if (index($i,"italic")) print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

전체 필드 정규식 일치

a) 단어 경계에 GNU awk 사용):

$ awk '/\<italic\>/{print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

b) awk를 사용하십시오.

$ awk '/(^|[[:space:]])italic([[:space:]]|$)/{print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

전체 필드 문자열 일치:

a) 루프를 사용하십시오.

$ awk '{for (i=1; i<=NF; i++) if ($i == "italic") print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

b) 루프 및 정규식 지원 없이:

$ awk 's=index($i,"italic") && (substr($0,s-1,1) ~ /^|[[:space:]]/) && (substr($0,s+length("italic"),1) ~ /[[:space:]]|$/){print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

위의 모든 항목은 게시한 예제 입력을 기반으로 예상되는 출력을 생성하며 문자열과 정규식, 정확한 일치와 부분 일치의 요구 사항에 따라 입력이 다르면 위의 모든 항목이 실패합니다.

답변2

패턴이 연속된 라인에 나타날 수 없는 경우 간단히 실행할 수 있습니다.

sed '$!N;/.*\n.*PATTERN.*/P;D' infile

나는 가지고있다여기에 설명되어 있습니다N루프 가 P작동 D합니다. 차이점은 여기서 패턴 공간의 첫 번째 라인은 두 번째 라인이 일치하는 경우에만 인쇄되고 그렇지 않으면 삭제된다는 것입니다.


패턴이 연속된 줄에 나타날 수 있는 경우 위의 솔루션은 일치하는 줄을 인쇄합니다(다른 일치하는 줄이 다음에 오는 경우).
연속 일치를 무시하려면 일치 항목이 없는 경우 패턴 공간의 첫 번째 줄만 인쇄하는 두 번째 조건을 추가하세요.

sed '$!N;/.*\n.*PATTERN.*/{/.*PATTERN.*\n.*/!P;};D' infile

또 다른 접근 방식은 보유 버퍼를 사용하는 것입니다.
연속 일치를 무시하려면 다음을 수행하십시오.

sed '/PATTERN/!{              # if line doesn't match PATTERN
h                             # copy pattern space content over the hold buffer
d                             # delete pattern space
}
//{                           # if line matches PATTERN
x                             # exchange pattern space with hold space
//d                           # if line matches PATTERN delete it
}' infile

아니면 한 줄로

sed '/PATTERN/!{h;d;};//{x;//d;}' infile

연속 일치를 무시하지 않으려면 다음을 수행하십시오.

sed '/PATTERN/!{              # if line doesn't match PATTERN
h                             # copy pattern space content over the hold buffer
d                             # delete pattern space
}
//x                           # if line matches PATTERN exchange buffers
' infile 

아니면 한 줄로

sed '/PATTERN/!{h;d;};//x' infile

그러나 예약된 버퍼를 사용하는 두 솔루션 모두 파일의 첫 번째 줄이 일치하면 앞에 빈 줄이 인쇄된다는 점을 명심하세요. 이것이 문제인 경우 1d첫 번째 확인 후에 //예를 들어
sed '/PATTERN/!{h;d;};//{1d;x;//d;}'sed를 추가하십시오.'/PATTERN/!{h;d;};//{1d;x;}'

답변3

사용grep, 그 다음에sed:

grep --no-group-separator -B 1 "italic" <yourfilename> | sed -n 1~2p`

설명하다:

grep수동:

-B num
--before-context=num
Print num lines of leading context before matching lines

--no-group-separator
When -A, -B or -C are in use, do not print a separator between groups of lines.

sed:

두 행 중 첫 번째 행을 선택합니다. sed -n 1~5p를 입력하여 5개 중 첫 번째를 선택할 수도 있습니다.

관련 정보