여러 줄 코드를 sed로 바꾸는 방법?


9

특수 문자가있는 큰 파일이 있습니다. 로 바꾸고 싶은 멀티 라인 코드가 sed있습니다.

이:

  text = "\
    ------                                                           ------\n\n\
    This message was automatically generated by email software\n\
    The delivery of your message has not been affected.\n\n\
    ------                                                           ------\n\n"

이것으로 전환해야합니다 :

text = ""

다음 코드를 시도했지만 운이 없습니다.

sed -i '/  text = "*/ {N; s/  text = .*affected.\./  text = ""/g}' /etc/exim.conf

아무것도 대체하지 않으며 오류 메시지를 표시하지 않습니다

나는 그것을 가지고 놀고 있지만 시도하는 모든 것이 작동하지 않습니다.


sed다른 도구가 필요합니까 아니면 다른 도구를 사용할 수 있습니까? 블록 "안에 있을 수 text=있습니까? text = 파일에 다른 경우가있을 수 있습니까? 항상 4 줄의 텍스트가 있거나 더 많거나 적을 수 있습니까?
terdon

가급적 sed이거나 CentOS 서버에 설치하지 않아도되는 것이 좋습니다. 즉시 사용 가능한 도구
blade19899

@terdon text = 폴더에 다른 폴더 가 없습니다 . out은이어야합니다 text = "". 파일에는 891 줄의 코드가 있습니다. 따라서 다른 텍스트를 존중해야합니다.
blade19899

파일을 덮어 쓰거나 출력을 수정 하시겠습니까?
joH1 2019

@Moonstroke 덮어 쓰지 않습니다. 내 질문에서 볼 수 있듯이 텍스트를 바꿔야합니다 text = "". 내 질문에서 볼 수 있듯이.
blade19899

답변:


15

구조에 펄 :

perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
  • -i~ 파일을 "제자리에서"편집하고 백업 사본을 남깁니다.
  • -0777 한 줄씩이 아닌 전체 파일을 한 번에 읽습니다.

대체 s///는 sed에서와 유사하게 작동합니다 (즉 text = ", 큰 따옴표와 여러 번 큰 따옴표까지 일치 합니다).이 경우 전체 파일에서 작동합니다.


5

패턴 공간을 확인하고 N일치하지 않는 경우 계속 연장선을 당겨야합니다.

sed '/text = "/{              # if line matches text = "
:b                            # label b
$!N                           # pull in the next line (if not the last one)
/"$/!bb                       # if pattern space doesn't end with " go to label b
s/".*"/""/                    # else remove everything between the quotes
}' infile

으로 gnu sed당신이로 쓸 수 있습니다

sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile

그래도 효율적이지 않습니다. 범위를 선택 /text = "/,/"/하고 첫 번째 줄을 수정하고 나머지를 삭제하십시오.

sed '/text = "/,/"/{            # in this range
/text = "/!d                    # delete all lines not matching text = "
s/\\/"/                         # replace the backslash with quotes (this is only
}' infile                       # executed if the previous d wasn't executed)

다시 한번, gnu sed하나의 라이너로 작성할 수 있습니다.

sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile

3

개인적으로 나는 이것을 Perl에서 할 것이다. "폐회 전이 없다고 가정 "할 수 있다면 다음을 수행 할 수 있습니다.

perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file

-0메모리에 읽기, 전체 파일을 slurps. -p수단 "에 의해 주어진 스크립트를 적용한 후"(될 것입니다 전체 파일 라인 여기하는) 모든 라인을 인쇄 " -e". 스크립트 자체는 간단한 대체 연산자입니다. 문자열 text뒤에 0 개 이상의 공백 문자 =와 0 개 이상의 공백 문자를 다시 캡처하고 ( text\s*=\s*) 다른 이름으로 저장합니다 $1. 그런 다음 캡처 된 패턴과 가장 짧은 인용 문자열을 패턴 ( $1) 및으로 바꿉니다 "". s플래그하게 .일치 뉴 라인.


수정, -00전체 파일이 아닌 단락을 읽습니다 ( ref ). 따옴표 안의 텍스트에 빈 줄이 있으면 정규식이 일치하지 않습니다.
glenn jackman

@glennjackman 아아! 나는 항상 그것들을 섞습니다. . 그래서 추가 단락을 추가하고 실행하여 실제로 두 번 확인했습니다 perl -00ne 'print;exit'. 그리고 나는 여전히 내 대답에 잘못된 것을 넣었습니다! 고마워, 지금 고쳐
terdon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.