개행 문자가 포함된 문자열 바꾸기

개행 문자가 포함된 문자열 바꾸기

셸을 사용하여 bash다음 줄이 포함된 파일에서

first "line"
<second>line and so on

하나 이상의 항목을 매번 다음 "line"\n<second>으로 바꾸고 싶습니다 .other characters

first other characters line and so on

"그래서 문자열을 및 같은 특수 문자로 바꾸고 <개행 문자로 바꿔야 합니다.

다른 답변 중에서 검색한 후 sed명령의 오른쪽(따라서 문자열 other characters)에서는 개행을 허용할 수 있지만 왼쪽에서는 허용되지 않는다는 것을 발견했습니다.

어떤 방법이 있습니까 (보다이것) sed이 결과를 얻으려면 또는 grep?

답변1

글쎄, 나는 몇 가지 간단한 방법을 생각할 수 있지만 grep(어쨌든 교체를 수행하지 않음) 또는 sed.

  1. 바꾸다"line"\n<second>가 나타나면 other characters다음을 사용하세요.

    $ perl -00pe 's/"line"\n<second>/other characters /g' file
    first other characters line and so on
    

    또는 여러 개의 연속 발생을 하나로 처리 "line"\n<second>하고 모두 단일 항목으로 바꾸려면 다음 other characters을 사용하십시오.

    perl -00pe 's/(?:"line"\n<second>)+/other characters /g' file
    

    예:

    $ cat file
    first "line"
    <second>"line"
    <second>"line"
    <second>line and so on
    $ perl -00pe 's/(?:"line"\n<second>)+/other characters /g' file
    first other characters line and so on
    

    이로 -00인해 Perl은 "단락 모드"에서 파일을 읽게 됩니다. 즉, "줄" \n\n이 로 정의 되어 \n본질적으로 각 단락이 한 줄로 처리된다는 의미입니다. 따라서 교체는 개행 전체에서 일치합니다.

  2. $  awk -v RS="\n\n" -v ORS="" '{
          sub(/"line"\n<second>/,"other characters ", $0)
          print;
        }' file 
    first other characters line and so on
    

    기본 아이디어는 동일합니다. 레코드 구분 기호( RS)를 설정하여 \n\n전체 파일을 삭제한 다음, 출력 레코드 구분 기호를 공백으로 설정한 다음(그렇지 않으면 추가 줄 바꿈이 인쇄됩니다), 이 sub()함수를 사용하여 이를 대체합니다.

답변2

전체 파일을 읽고 전역 교체를 수행합니다.

sed -n 'H; ${x; s/"line"\n<second>/other characters /g; p}' <<END
first "line"
<second> line followed by "line"
<second> and last
END
first other characters  line followed by other characters  and last

답변3

세 가지 다른 sed명령:

sed '$!N;s/"[^"]*"\n<[^>]*>/other characters /;P;D'

sed -e :n -e '$!N;s/"[^"]*"\n<[^>]*>/other characters /;tn'

sed -e :n -e '$!N;/"$/{$!bn' -e '};s/"[^"]*"\n<[^>]*>/other characters /g'

세 가지 모두 기본 s///대체 명령을 기반으로 구축되었습니다.

s/"[^"]*"\n<[^>]*>/other characters /

그들은 또한 마지막 줄에 주의를 기울이려고 노력합니다. 왜냐하면 sed출력이 극단적인 경우에 달라지는 경향이 있기 때문입니다. 이것이 의미하는 바는 $!마지막 줄이 아닌 모든 줄의 주소를 일치시키는 것입니다.!$

또한 둘 다 ext 명령을 사용하여 N패턴 공간의 \newline 문자 에 다음 입력 행을 추가합니다. sed한동안 이 문자를 사용해 온 사람 이라면 누구나 \newline 문자에 의존하는 방법을 배울 것입니다. 왜냐하면 그것을 얻는 유일한 방법은 명시적으로 거기에 넣는 것이기 때문입니다.

세 가지 모두 조치를 취하기 전에 가능한 한 적은 입력을 읽으려고 노력합니다. 조치를 sed취하기 전에 전체 입력 파일을 읽을 필요 없이 최대한 빨리 조치를 취합니다.

모두 그렇게 하지만 N세 가지 모두 서로 다른 재귀 방법을 가지고 있습니다.

첫 번째 명령

첫 번째 명령은 매우 간단한 N;P;D루프를 사용합니다. 이 세 가지 명령은 POSIX 호환 명령에 내장되어 있으며 sed서로를 잘 보완합니다.

  • N- 이전에 설명한 대로 삽입된 줄바꿈 구분 기호 N뒤의 패턴 공간 에 추가 입력 줄을 추가합니다.\n
  • P- p; 와 마찬가지로 P패턴 공간을 인쇄하지만 처음으로 나타나는 \newline 문자만 인쇄합니다. 따라서 다음 입력/명령이 제공됩니다.

    • printf %s\\n one two | sed '$!N;P;d'
  • sed P인쇄만 가능하나. 그러나 ...

  • D- 마찬가지로 d; D패턴 공간을 제거하고 또 다른 라인 루프를 시작합니다.같지 않은 d, 패턴 공간에서 처음으로 나타나는 ewline D만 삭제됩니다. ewline 문자 뒤의 패턴 공간에 더 많은 내용이 있는 \n경우 나머지 내용은 다음 줄 루프를 시작하는 데 사용됩니다. 예를 들어 이전 예에서 a를 바꾸면 다음도 인쇄됩니다.\nseddDsedP하나그리고.

이 명령은 다음 줄에서만 반복됩니다.원하지 않는다s///교체문을 일치시키세요 . 대체는 추가된 줄바꿈을 s///제거하기 때문에 패턴 공간을 삭제할 때 아무것도 남지 않습니다.\nNsed D

P및/또는 을 선택적으로 적용하기 위해 테스트를 수행할 수 있지만 D이 전략에 더 적합한 다른 명령이 있습니다. 일치하는 연속 행만 처리하도록 재귀가 구현되었기 때문입니다.부분연속 라인 시퀀스 일치에 대한 대체 규칙양쪽 끝대안이 s///잘 작동하지 않습니다.

다음 입력이 주어지면:

first "line"
<second>"line"
<second>"line"
<second>line and so on

...인쇄됩니다...

first other characters "line"
<second>other characters line and so on

그러나 그것은 처리합니다

first "line"
second "line"
<second>line

...바로.

두 번째 순서

이 명령은 세 번째 명령과 매우 유사합니다. 둘 다 :branch/ test 태그를 사용합니다.(Joseph R.의 답변도 이를 증명합니다.여기)특정 조건이 주어지면 재귀적으로 다시 돌아옵니다.

  • -e :n -e- 이식 가능한 스크립트는 ewline 또는 새로운 인라인 실행 문을 사용하여 sed레이블 정의를 구분합니다.:\n-e
    • :n- 라는 라벨을 정의합니다 n. 귀하는 언제든지 bn이 콘텐츠를 사용하거나 다시 돌아올 수 있습니다 tn.
  • tn- test 명령은 지정된 레이블을 반환합니다.(또는 제공되지 않은 경우 현재 라인 사이클에 대한 스크립트를 종료합니다)s///마지막 호출 이후 맞춤 태그나 교체 항목이 있으면 성공한 t것으로 간주됩니다.

이 명령에서는 일치하는 줄을 반복합니다. sed패턴을 다음으로 성공적으로 바꾸면다른 역할, 라벨 sed로 돌아가서 다시 시도하세요. 교체가 수행되지 않으면 :n패턴 공간이 자동으로 인쇄되고 다음 라인 주기가 시작됩니다.s///sed

이는 연속된 시퀀스를 더 잘 처리하는 경향이 있습니다. 마지막 것이 실패하면 다음을 인쇄하십시오.

first other characters other characters other characters line and so on

세 번째 주문

앞서 언급했듯이 여기의 논리는 이전 논리와 매우 유사하지만 테스트가 더 명확합니다.

  • /"$/bn- 이것은 sed테스트입니다. ranch 명령은 해당 주소의 함수이기 때문에 bewline이 추가되고 패턴 공간이 여전히 큰따옴표로 끝날 때까지 ranch는 반환 sed되지 않습니다 b.:n\n"

N및 사이에 가능한 한 적은 작업을 수행합니다 b. 이렇게 하면 sed다음 줄이 규칙과 일치하지 않도록 하는 데 필요한 정확한 입력을 매우 빠르게 수집할 수 있습니다. 교체는 전역 플래그를 s///사용한다는 점에서 다릅니다 g. 따라서 필요한 모든 교체를 한 번에 수행합니다. 동일한 입력이 주어지면 이 명령의 출력은 이전 명령과 동일합니다.

답변4

이것은 변형입니다글렌의 대답연속해서 여러 번 발생하는 경우 작동합니다( sedGNU에만 해당).

sed ':x /"line"/N;s/"line"\n<second>/other characters/;/"line"/bx' your_file

이것은 :x지점에 대한 레이블일 뿐입니다. 기본적으로 이것이 하는 일은 대체된 줄을 확인하고 여전히 일치하는 경우 레이블 "line"로 다시 분기하고 :x(이것이 바로 그 일입니다 bx) 버퍼에 다른 줄을 추가하고 처리를 시작하는 것입니다.

관련 정보