을 사용하여 sed
다음과 같이 패턴을 바꾸고 싶습니다.
--- >>> +++
--+-- >>> ++-++
--+-+-- >>> ++-+-++
--+-+-+-- >>> ++-+-+-++
...
--(+-)^n- >>> ++(-+)^n+
내가 작업 중인 문자열은 +와 -의 임의 목록입니다.
--+++-+--+--++-+--++--+-+--++--+-++-+-
나는 이것을 시도했지만 작동하지 않습니다.
sed '/--\<+-\>*-/{s/+/A/g;s/-/+/g;s/A/-/g}'
위의 예에서는 다음과 같은 결과가 나올 것으로 예상됩니다.
--+++-+--+--++-+--++--+-+--++--+-++-+- (input)
--+++-+++-++++-+--++++-+-++++--+-++-+- (output)
!!!!! !!!!!!!
(느낌표는 변경된 영역을 나타냅니다.)
답변1
정규식과 일치하는 주소 부분만 수정하려고 하는데 주소가 일치하면 대체 내용이 전체 줄에 영향을 줍니다. 트릭은 변환을 적용할 때 변경하려는 항목만 패턴 공간에 포함시키는 것입니다. 이 명령의 기능은 다음과 같습니다.
sed '/--\(+-\)*-/{:a;h;s/.*\(--\(+-\)*-\).*/\1/;y/+-/-+/;G;s/\(.*\)\n\(.*\)--\(+-\)*-\(.*\)/\2\1\4/;/--\(+-\)*-/ba}' <<< '--+++-+--+--++-+--++--+-+--++--+-++-+-'
나조금더 쉽게 읽을 수 있습니다:
/--\(+-\)*-/ { # Match a line containing the pattern
:start # Label to branch back to
h # Copy pattern space to hold space
s/.*\(--\(+-\)*-\).*/\1/ # Remove everything but pattern
y/+-/-+/ # Swap + and -
G # Append hold space to pattern space
s/\(.*\)\n\(.*\)--\(+-\)*-\(.*\)/\2\1\4/ # Rearrange pattern space
/--\(+-\)*-/b start # If there are more occurrences, branch to start
}
댓글로는 작동하지 않을 수도 있으니, y
문제가 있는 것 같으니 주의하시기 바랍니다.
샘플 문자열로 테스트합니다.
$ sed -f sedscr <<< '--+++-+--+--++-+--++--+-+--++--+-++-+-'
--+++-+++-++++-+--++++-+-++++--+-++-+-
질문의 sed 명령에 대해 언급할 두 가지 사항이 있습니다.
\<
단어 경계 와\>
일치하지만 다음 기준으로만 그룹화하려고 합니다.\(\)
- 문자의 직접 매핑을 변경하려면
y
여러 대체 대신 변환 명령을 사용할 수 있습니다