줄 바꿈 문자가 포함 된 문자열 교체 문자로. 다른 답변 사이에서 검색 한 후 sed명령의

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?



답변

세 가지 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///ubstitution 명령을 기반으로합니다 .

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

또한 sed에지 라인 의 출력이 서로 다른 경향이 있기 때문에 마지막 라인을 다룰 때주의를 기울입니다 . 이것은 의미가 마지막 $!!아닌 모든 행과 일치하는 주소 $입니다.

또한 모두 Next 명령을 사용하여 다음 입력 행을 추가하여 \newline 문자 다음의 패턴 공간에 추가합니다 . sed한동안 지낸 사람이라면 누구나 \newline 특성 에 의존하는 법을 배웠을 것입니다. 왜냐하면 그것을 얻는 유일한 방법은 그것을 명시 적으로 넣는 것뿐이기 때문입니다.

세 가지 모두 조치를 취하기 전에 가능한 한 적은 양의 입력을 읽으려고 시도합니다 sed. 그렇게하기 전에 전체 입력 파일에서 읽거나 읽을 필요가없는 한 빨리 작동합니다.

비록 그들이 모두했지만 N, 세 가지 모두 재귀 방법이 다릅니다.

첫 번째 명령

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

  • N-이미 언급했듯이 N삽입 된 \newline 구분 기호 다음에 ext 입력 행을 패턴 공간에 추가합니다 .
  • P-같은 p; 그것은 P그러나 첫 번째 발생까지 -에 – 패턴 공간 rints \newline 문자. 따라서 다음과 같은 입력 / 명령이 주어집니다.

    • printf %s\\n one two | sed '$!N;P;d'
  • sed P단지 rints 하나 . 그러나 …

  • D-같은 d; 이 D패턴 공간을 eletes 다른 라인 사이클을 시작한다. 달리 d , D단지까지 첫 번째 발생을 삭제 \n패턴 공간에서 ewline. \newline 문자 다음에 패턴 공간이 더 있으면 sed남은 줄로 다음 줄주기를 시작합니다. 경우 d앞의 예에서이 교환되었다 D, 예를 들어, sedP모두 RINT 하나 .

이 명령 은 ubstitution 문과 일치 하지 않는 행에 대해서만 반복됩니다 s///. 때문에 s///ubstitution가 제거 \n로 추가 ewline을 N때 나머지 결코 아무것도가 sed Deletes 패턴 공간을.

P및 / 또는 D선택적으로 적용하기 위해 테스트를 수행 할 수 있지만 해당 전략에 더 적합한 다른 명령이 있습니다. 대체 규칙의 일부 에만 일치하는 연속 행을 처리하기 위해 재귀가 구현되므로, ubstitution 의 양쪽 끝 과 일치하는 연속적인 행 시퀀스 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

… 괜찮아.

두 번째 명령

이 명령은 세 번째와 매우 유사합니다. 둘 다 :b목장 / test 레이블을 사용하고 ( 여기서 Joeseph R.의 답변에 설명되어 있음 ) 특정 조건에서 다시 되풀이 됩니다.

  • -e :n -e-이식 가능한 sed스크립트는 ewline 또는 새로운 인라인 xecution 문 으로 :레이블 정의를 구분합니다 .

    \n-e

    • :n-라는 레이블을 정의합니다 n. bn또는 을 사용하여 언제든지 되돌릴 수 있습니다 tn.
  • tnt지정된 라벨로 추정 명령이 리턴 (없음이 제공되지 않은 경우 또는, 현재 행주기위한 스크립트를 종료) 이있는 경우 s///ubstitution 레이블 중 하나가 정의 된 이후 또는가 마지막으로 시작된 이후라는 t성공적인 ESTS을.

이 명령에서 일치하는 행에 대해 재귀가 발생합니다. 경우 sed성공적으로 패턴 대신 다른 문자 , sed받는 돌아 :n다시 레이블과 시도를. 경우 s///ubstitution이 수행되지 않습니다 sedautoprints에게 패턴 공간을 다음 행주기를 시작한다.

이것은 연속 시퀀스를 더 잘 처리하는 경향이 있습니다. 마지막 것이 실패하면 다음과 같이 인쇄됩니다.

first other characters other characters other characters line and so on

세 번째 명령

언급했듯이 여기의 논리는 마지막과 매우 유사하지만 테스트는 더 명확합니다.

  • /"$/bn-이건 sed테스트 야 때문에 b목장 명령이 주소의 함수이며, sed의지 만 b에 목장 다시 :n\newline이 추가 및 패턴 공간이 여전히으로 끝 "따옴표.

적게 사이에 다있다 N하고 b가능한 한 -이 방법으로 sed매우 빠르게 다음 줄이 규칙과 일치하지 수 있도록 필요한만큼 입력으로 정확하게 수집 할 수 있습니다. s///여기가 사용하는 것을 ubstitution의 다릅니다 g은 한 번에 모든 필요한 교체 할 수 있도록하고 – lobal 플래그. 동일한 입력이 주어지면이 명령은 마지막과 동일하게 출력됩니다.


답변

글쎄, 나는 몇 가지 간단한 방법을 생각할 수 있지만 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“선”에 의해 정의됨을 의미 ‘단락 모드 “에서 파일 읽기 펄 발생 \n\n않고 \n본질적으로, 각각 단락 선으로 처리된다. 따라서 대체는 개행에서 일치합니다.

  2. 어 wk

    $  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()함수를 사용하여 교체합니다.


답변

전체 파일을 읽고 전체 대체를 수행하십시오.

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

답변

다음 은 여러 번 연속적으로 발생하는 경우 작동하는 glenn의 답변 변형입니다 (GNU sed에서만 작동 ).

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

이는 :x분기를위한 레이블 일뿐입니다. 기본적으로 이것이하는 것은 대체 후 라인을 확인하고 여전히 일치 "line"하는 경우 :x레이블로 다시 분기 bx되어 버퍼에 다른 라인을 추가하고 처리를 시작한다는 것입니다.