원하는 수의 단어 바꾸기 [닫기]

원하는 수의 단어 바꾸기 [닫기]

을 사용하여 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여러 대체 대신 변환 명령을 사용할 수 있습니다

관련 정보