여기서부터 시작해야 합니다.
text match$something_here and match$xxx blablabla
text match$something_else_here and match$xxx blablabla
...
이와 관련하여:
text match$something_here and match$something_here blablabla
text match$something_else_here and match$something_else_here blablabla
...
따라서 파일의 각 줄에 대해 xxx
두 번째 발생 이후의 내용 match$
과 첫 번째 발생 이후의 내용을 변경해야 합니다 match$
.
답변1
:%s/match\$\zs\(\w\+\)\(.*match\$\)xxx/\1\2\1/
설명하다
match\$\zs
: 처음에 경기 고정match$
; 다른 캡처 그룹을 피하기 위해 보통\zs
그 후에 경기를 시작합니다.\(\w\+\)
: 첫 번째 발생 이후 텍스트 캡처match$
\(.*match\$\)
: 두 번째 발생할 때까지 뒤에 오는 내용을 캡처match$
하고 유지하려는 내용을 캡처합니다.xxx
: 대체된 콘텐츠와 일치
대안: 첫 번째 항목 이후의 텍스트, 그 사이의 텍스트, 첫 번째 텍스트(교체 xxx
)입니다.
답변2
이 시도:
sed -e 's/\(match\$\)\([a-zA-Z_]\+\)\([a-zA-Z ]\+match\$\)[a-zA-Z]\+/\1\2\3\2/' < input.txt > output.txt
input.txt
다음 중 하나를 사용하십시오 .
text match$something_here and match$xxx blablabla
text match$something_else_here and match$xxx blablabla
나는 다음을 얻습니다 output.txt
:
text match$something_here and match$something_here blablabla
text match$something_else_here and match$something_else_here blablabla
답변3
:%s/\v(match\$(\w+).*match\$)xxx/\1\2/
- \v는 놀랍습니다(\\를 더 적게 사용할 수 있습니다)
답변4
sed -e 's/\(match\)\([_[:alnum:]]*\)\(\(.*\)\n\)*/\1\
/2;tc' -e b -e :c -e 's//\1\2\4\2/'
위의 시퀀스는 match
행에 몇 개가 있는지에 관계없이 항상 행의 첫 번째와 두 번째 항목만 처리합니다.
s///
패턴의 cd 발생 시 첫 번째 대체를 수행한 s///2
다음 대체가 t
성공 하면 연속 태그 b
로 분기하고 :c
, b
성공하지 못하면 스크립트에서 분기하는 방식으로 작동합니다.
따라서 두 번째 일치에 대해 패턴이 발생하면 s///
2cd 대체 명령에 대해 패턴이 반복됩니다. 그러나 그렇지 않은 경우 해당 줄은 평소대로 인쇄됩니다.
중요한 것은 \(\(.*\)\n\)*
하위 표현식입니다. ewline은 편집 결과로 패턴 공간에만 나타날 수 있기 s///2
때문에 이 하위 표현식은 첫 번째 명령의 빈 문자열에만 일치합니다 . 그러나 패턴이 반복되면 이전 교체가 교체 시 ewline을 삽입했기 때문에 두 es 사이에 발생하는 모든 문자가 일치됩니다 . 따라서 동일한 반복 패턴은 스크립트의 컨텍스트에 따라 두 가지 다른 의미를 가질 수 있습니다.\n
sed
\(\(.*\)\n\)*
match
s///
\n
[_[:alnum:]]*
위 버전이기는 하지만~해야 한다모든 POSIX에 대해 작성된 대로 작동합니다.sed
(강조하다~해야 한다- 많은 sed
s가 반복된 하위 표현 기준을 충족하지 않습니다), GNU를 사용하면 sed
더 짧게 작성할 수 있습니다.
sed -E 's/(match)(\w*)((.*)\n)*/\1\n/2;T;s//\1\2\4\2/
' <<\IN
text match_something_here and !m!atch_xxx blablabla
text match_something_here and match_xxx blablabla
text match_something_else_here and match_xxx blablabla
text match_something_here and match_xxx blablabla match_xxx blablabla
text match_something_else_here and match_xxx blablabla match_xxx blablabla match_xxx blablabla
IN
... 비트 <<\IN
전달은 IN
여기 문서에 대한 입력일 뿐이므로 어떻게 작동하는지 보여줄 수 있습니다. 아마도 <input_file
그 자리에서 사용해야 할 것입니다. 또한 내가 당신 $something
과 를 변경했다는 점에 유의하세요. $xxx
왜냐하면 _something
달러 _xxx
기호는 실제로 대체 패턴에 포함되어서는 안 되며 다른 것으로 대체되어야 한다는 것입니다. true인 경우 \w*
ord 이스케이프를 그대로 둘 수 있습니다. 또는 문자 그대로 달러 기호를 포함하려면 여전히 고유한 문자 클래스를 정의하고 다음과 같이 추가해야 합니다 [$_[:alnum:]]*
.
tc' -e b -e :c -e
GNU에서는 sed
est가 1로 단축됩니다 T
. 그러나 이식 가능한 est 는 실패한 행의 범위를 넘어서 t
성공적으로 교체되는 반면, GNU에서는 est를 사용하여 실패한 결과를 얻을 수 있습니다 . 그 시점에서 여전히 스크립트를 실행하는 라인은b
b
sed
T
했다\n
라인을 두 번째 일치하는 쌍으로 성공적으로 교체했습니다 .
어떤 경우 에라도,(에 따라 sed
)위의 내용 중 하나가 인쇄됩니다.
text match_something_here and !m!atch_xxx blablabla
text match_something_here and match_something_here blablabla
text match_something_else_here and match_something_else_here blablabla
text match_something_here and match_something_here blablabla match_xxx blablabla
text match_something_else_here and match_something_else_here blablabla match_xxx blablabla match_xxx blablabla