나는 이 파일을 가지고 있습니다 :
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을 얻는 유일한 시간은 입력 라인이 일치할 때 ^}
(범위의 끝)이므로 다른 경우에 스크립트를 다시 실행하면 평소처럼 다음 입력 라인을 가져옵니다.
그러나 PATTERN
ewline과 동일한 패턴 공간에서 발견 되면 \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
{
}
PATTERN
PATTERN
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
--> 쿼리에 언급된 파일의 내용을 포함합니다.