문자열을 검색하고 범위 앞과 뒤의 모든 내용을 인쇄합니다.

문자열을 검색하고 범위 앞과 뒤의 모든 내용을 인쇄합니다.

나는 이 파일을 가지고 있습니다 :

sometext1{
string1
}

sometext2{
string2
string3
}

sometext3{
string4
string5
string6
}

이 파일에서 특정 문자열을 검색하고 해당 문자열 이전의 모든 항목을 처음부터 인쇄하고 {해당 문자열 이후의 모든 항목을 끝까지 인쇄하고 싶습니다 }. 이를 달성하기 위해 sed를 사용해 보았지만 범위 내의 모든 내용을 인쇄하려고 하면 /{/,/string2/예를 들어 sed가 다음을 인쇄합니다.

sometext1{
string1
}

sometext2{
string2
sometext3{
string4
string5
string6
}

문자열 "string2"를 검색하면 다음과 같은 출력이 필요합니다.

sometext2{
string2
string3
}

감사해요.

답변1

여기에는 두 가지 명령이 있습니다. .*{$시퀀스의 마지막 줄 까지 자르는 명령을 원하는 경우(@don_crissti가 그랬듯이 ed)넌 할 수있어:

sed 'H;/{$/h;/^}/x;/{\n.*PATTERN/!d'

...이것은 ewline 문자 H뒤의 이전 공간 에 각 줄을 추가하고 \n, h일치하는 각 줄의 이전 공간을 덮어쓰고, {$일치하는 각 줄의 h이전 공간과 패턴 공간을 교체 ^}하여 버퍼를 플러시하는 방식으로 작동합니다.

이는 ewline {과 일치하는 행만 인쇄 \n한 다음 PATTERN특정 지점에서 인쇄하며 이는 버퍼 스왑 직후에만 발생합니다.

{$시퀀스의 마지막 일치 항목까지 일련의 일치 항목에서 모든 행을 제거 하지만 포함된 모든 행을 가져올 수 있습니다. 예를 들면 다음과 같습니다.

sed '/PATTERN.*\n/p;//g;/{$/,/^}/H;//x;D'

그것이 하는 일은 h각 시퀀스에 대한 패턴과 이전 공백을 바꾸고 ...{$.*^}.*, 시퀀스의 모든 행을 이전 행 문자 H뒤의 이전 공백 에 추가하고 \n, 각 행을 반복하여 패턴 공간에서 처음으로 나타나는 ewline 문자를 D제거하는 것 입니다. \n그런 다음 나머지 콘텐츠부터 시작하세요.

물론 \n패턴 공간에서 ewline을 얻는 유일한 시간은 입력 라인이 일치할 때 ^}(범위의 끝)이므로 다른 경우에 스크립트를 다시 실행하면 평소처럼 다음 입력 라인을 가져옵니다.

그러나 PATTERNewline과 동일한 패턴 공간에서 발견 되면 \n배치를 다시 덮어쓰기 전에 인쇄합니다 .^}(범위를 종료하고 버퍼를 플러시할 수 있도록).

이 입력 파일이 주어지면(돈님 감사합니다):

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}
}

첫 번째는 다음과 같이 인쇄됩니다.

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}

...그리고 두 번째...

sometext2{
PATTERN
string3
}
Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}

답변2

해결책은 다음과 같습니다 ed.

ed -s filename <<< $'g/PATTERN/?{?,/}/p\nq\n'

그건:

g/PATTERN/     # mark each line matching PATTERN  
?{?,/}/p       # for each marked line, print all lines from the previous { up to the next }  
q              # quit editor

PATTERN이는 각 쌍 사이에 하나의 행만 있다고 가정합니다. 그렇지 않으면 동일한 블록 내의 { }각 추가 행에 대해 중복 출력을 얻게 됩니다 . 이는 두 개의 서로 다른 섹션을 포함하는 테스트 파일과 같이 한 줄 일치를 포함하는 여러 파일에서 작동합니다.PATTERN
{ }PATTERNPATTERN

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN again

another string here
}
}

달리기

ed -s sample <<< $'g/PATTERN/?{?,/}/p\nq\n'

산출:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN again

another string here
}

답변3

그리고 pcregrep:

pcregrep -M '(?s)\{[^}]*PATTERN.*?\}'

또는 grep입력에 NUL 바이트가 포함되지 않은 경우 GNU 를 사용하십시오.

grep -Poz '.*(?s)\{[^}]*PATTERN.*?\}'

답변4

$ awk 'BEGIN{RS="\n\n"; FS="[{}]"} {if ($2 ~ /string4/) {print $2}}' t1.txt
string4
string5
string6

어디:

  • string4--> 일치시킬 문자열
  • t1.txt--> 쿼리에 언급된 파일의 내용을 포함합니다.

관련 정보