만약 내가한다면:
sed 's/match/replace/g'
나는 그것이 sed
대체할 것이라는 것을 안다.바꾸다모든 사건에 대해성냥줄에. 하지만 만약...?
echo "match <please dont match this?>" |
sed 's/match/replace/g'
...또는...
echo "never match unless <the match is somehow delimited?>" |
sed 's/match/replace/g'
t
est 또는 b
ranch 루프를 사용하여 개별적으로 재귀적으로 일치시킬 수 있다는 것을 알고 있지만 s///g
전역 일치 컨텍스트에서 줄의 일부를 건너뛰려면 어떻게 해야 합니까?
답변1
내용은 sed
이렇습니다탐욕스러운. 모든 상황에서 가능한 한 많이 잡아먹습니다. 이는 s///g
부분 교체 환경에서 이점을 제공할 수 있습니다. 귀하의 \(
그룹이\)
*
0 이상문자열 일치는 sed
어떤 경우에도 첫 번째 문자열을 전역적으로 삼킵니다. g
따라서 안정적으로 정의할 수 있다면/이것과 일치/ |이것을 건너뛰세요|이렇게 할 수 있는 경우:
sed 's/\([^<>]*<\)*\(match *\)*\(remove *\)*/\1/g
s/.\{,45\}[^ ]*/&\
/g; s/\(\n\) */\1/g
' <<INPUT
Never remove any match unless <the match \
you want to remove is somehow delimited.> \
And you can remove any match <per your match \
delimiter as many times as your match occurs \
within the match delimiters.>
INPUT
산출
Never remove any match unless <the you want to
is somehow delimited.> And you can remove any
match <per your delimiter as many times as your
occurs within the delimiters.>
쉘이 여기 문서의 백슬래시에서 개행을 이스케이프하기 때문에 입력은 한 줄입니다. sed
45자로 분할하세요.(주거나 받거나)테두리를 만들어 인쇄하세요. 그럼에도 불구하고 보시다시피 두 가지 조건 중 하나가 발생할 때마다성냥또는제거하다밖에 하나<...>경계는 그대로 유지되지만 모든 내부 경계는 출력에서 제거됩니다.
sed
이는 일치하는 항목에 적용되는 탐욕 함수입니다 .*
0 이상이류. 부정하는 데 한두 단계만 추가하면 됨에도 불구하고 대체가 동일한 방식으로 작동하는 것을 불가능하게 만드는 것은 이러한 탐욕입니다.
이것이 어떻게 작동하는지 명확하게 보기 위해 대체를 수행할 수 있습니다. 그런데 직접 적용하면 일반적으로 별로 유용하지 않습니다.
printf '%s %s\n' '<321Nu0-9mber123>' \
'String321strinG' \
'<321Nu0-9mber123>' \
'String321strinG' |
sed 's/\(<[^<>]*>\)*[0-9]*/\1!/g'
산출
<321Nu0-9mber123>! !S!t!r!i!n!g!s!t!r!i!n!G!
<321Nu0-9mber123>! !S!t!r!i!n!g!s!t!r!i!n!G!
따라서 sed
전역 패턴에서 선을 일치시킬 때 특징적인 욕심을 유지하면서 가능한 한 많은 패턴을 일치시키려고 합니다. 모드가 탐욕적일 때의 부작용0 이상지정된 발생이 행의 일부와 일치하지 않습니다.여전히 일치- 빈 문자열과 일치합니다.~ 사이줄 부분의 바이트를 일치시킬 수 없습니다.
위에 보시면 아시겠지만<...>문자열은 영향을 받지 않지만, 그 안에 있는 숫자는끈...사라졌을 뿐만 아니라, sed
캐릭터별로 뱅이 삽입되었습니다. 이는 sed
빈 문자열과의 모든 일치 항목을 반영합니다. 이것이 바로 이 기술이 g
전 세계적으로 유용한 이유입니다.정의하다하나를 수행하는 대신 경기를 대체하십시오.
작동 방식은 다음과 같습니다.
printf '%s\t%s\n' '<321Nu0-9mber123>' \
'String321strinG' \
'<321Nu0-9mber123>' \
'String321strinG' |
sed 's/[0-9]/&\n/g;s/\(<[^<>]*>\)*\n*/\1/g;y/\n/0/'
산출
<302010Nu00-90mber102030> String321strinG
<302010Nu00-90mber102030> String321strinG
<
이는 매우 간단한 경우인 and에 나타나는 모든 숫자에 0을 추가 >
하지만 실제로는 \n
전역 대체를 수행하기 위해 이런 방식으로 ewline 문자를 사용할 수 있습니다.어느성냥. 기본 원칙은 다음과 같습니다.
- 하다
sed 's/match/&\n/g'
- 그럼 해
sed 's/\(match group\)*\n*/\1/g'
- 마지막으로 할 일
sed 's/match\n/replace/g'
물론, 이 예제는 단순 목록 예제( <
항상 맨 위에 있음 )만을 보여줍니다 >
. 둥지도 고려해야합니다. 더 어렵습니다. 때로는 더 어렵습니다. 하지만 음...
sed 's/\([{}]\)\([^{}]*[{}]*\1\)*/\n<&>/g
' <<\INPUT
{{{1!}{2!}{3!}}}outside!{{{4!}}{{5!}}}
INPUT
산출
<{{{1!}{2!}{>3!
<}}}>outside!
<{{{4!}}{{>5!
<}}}>
개행 문자로 그룹을 직렬화합니다. 동일한 유형의 구분 기호를 연속으로 두 번 쌓으면서 각 일치 그룹과 일치하는 구분 기호를 번갈아 가며 작동합니다.(적어도 두 번)부작용은 시가와 종가를 비교하는 것입니다. 즉, 단순화를 위해 나머지 부분에서는 모든 독자가 입력을 준비하기 위해 유사한 방법을 사용할 것이며 중첩은 문제가 되지 않는다고 가정합니다.
본질적으로 이 모든 것의 기본 아이디어는 우선순위를 일치시키는 것입니다. 첫 번째 예는 제거된 문자열과 일치시키기 전에 열린 구분 기호 바로 앞에 있는 구분 기호가 없는 문자 그룹과 일치를 시도하는 방식으로 작동합니다. 첫 번째 세트가 일치하면 교체가 완료되면 일치하는 전체 세트만 자체적으로 교체할 수 있으므로 교체가 어려워지는 이유가 됩니다. 제거하는 것이 더 간단합니다. 일치하는 항목을 교체에서 제외하면 괜찮기 때문입니다.
또한 sed
다른 패턴보다 특정 유형의 패턴을 더 강조합니다. 이 작업을 수행할 때 다음을 이해하는 것이 중요합니다.정말지정된 패턴은 항상 패턴보다 더 많은 가중치를 갖습니다.*
0 이상사례. 따라서 전역 모드에 이러한 항목을 사용할 때는 *
해당 항목만 사용하거나 전혀 사용하지 마십시오. 그렇지 않으면 모든 그룹을 전혀 건너뛰게 될 수 있습니다.
방법은 다음과 같습니다 sed
.