sed/awk/perl을 사용하여 입력 파일의 줄을 바꾸는 방법

sed/awk/perl을 사용하여 입력 파일의 줄을 바꾸는 방법

입력 파일의 경로를 바꾸려고 합니다.

    #include "../../../Plumed.h"         #### this is old patch in input 

    #include "/usr/local/include/Plumed.h  #### this should be the new path

이전에 답변한 질문을 본 후(https://stackoverflow.com/questions/11245144/replace-whole-line- Contains-a-string-using-sed).

나는 이것을 시도했다.

    sed -i '/../../../Plumed.h/c\/usr/local/include/Plumed.h' ../dist0.xvg


    perl -i -pe 's/../../../Plumed.h/usr/local/include/Plumed.h/g' ../dist0.xvg

나는 sed/perl이 혼란스러워지고 있다고 생각하지만 이 문제를 극복하는 방법을 모르겠습니다. 어떤 도움이라도 대단히 감사하겠습니다.

답변1

TL, 박사:

사용:

sed -i 's:"\.\./\.\./\.\./Plumed\.h":"/usr/local/include/Plumed.h":g' ../dist0.xvg

시도한 Sed 명령에 대한 몇 가지 의견:

sed -i '/../../../Plumed.h/c\/usr/local/include/Plumed.h' ../dist0.xvg
  • -i이식성이 없으므로 GNU Sed를 사용하고 있는 것 같습니다.

    BSD Sed -i에도 스위치가 있지만 백업 확장자는 필수 매개변수이므로 BSD Sed에 백업을 저장하지 않고 파일을 수정하는 것이 필요하다 -i ''.

    -i다른 버전의 Sed에는 스위치가 전혀 없을 수도 있습니다.

  • 여기의 정규식에는 /../../../Plumed.h/정규식 구분 기호의 여러 복사본이 포함되어 있습니다.

    일반적인 해결책은 구분 기호를 이스케이프 처리하는 것입니다.

    /..\/..\/..\/Plumed.h/
    

    그러나 Sed에 대해서는 알려진 사실이 거의 없습니다.어느s백슬래시로 첫 번째 인스턴스를 이스케이프하면 정규식 구분 기호입니다(명령뿐만 아니라). (거의 모든 것 - 백슬래시나 개행 문자는 허용되지 않습니다.)

    인용하다POSIX 사양곧장:

    컨텍스트 주소에서 " \cBREc"를 구성합니다.<backslash>또는 를 제외한 모든 문자 <newline>이며 " "와 동일해야 합니다 /BRE/. 지정된 문자인 경우뒤에 나타나는 문자 <backslash>는 BRE를 종료하지 않는 리터럴 문자로 처리됩니다. 예를 들어 컨텍스트 주소 " \xabc\xdefx"에서 두 번째엑스자신을 나타내므로 BRE는 " abcxdef"입니다.

    따라서 "기울어진 이쑤시개 증후군"을 방지하려면 다음 두 정규 표현식이 동일하다는 점에 유의하세요.

    /..\/..\/..\/Plumed.h/
    \:../../../Plumed.h:
    

    내가 "동등하다"고 말했음을 참고하세요아니요옳은. 이것은 다른 답변이 놓친 다음 요점으로 연결됩니다.

  • 정규식의 마침표( )는 다음 .을 나타냅니다.모든 문자.

    리터럴 마침표만 일치시키려면 백슬래시를 사용하여 마침표를 이스케이프하거나 에서와 같이 문자 클래스에 붙여 넣을 수 있습니다 [.].

    따라서 리터럴 마침표만 일치시키려면 정규식은 실제로 다음과 같아야 합니다.

    \:\.\./\.\./\.\./Plumed\.h:
    

    이쑤시개가 기울어지는 것을 방지하기 위해 너무 많은 것입니다.

    아마도 더 읽기 쉬운 형식을 사용할 수도 있습니다.

    \:[.][.]/[.][.]/[.][.]/Plumed[.]h:
    
  • 명령 c이 변경되었습니다.전선, 정규식과 일치하는 줄 부분만이 아닙니다.

    s행의 일부만 변경하려면 이 명령을 사용하십시오 .

    s이 명령을 사용하면 주소에 대체 구분 기호를 사용할 때처럼 첫 번째 정규식 구분 기호(구분 기호로 사용되는 특이한 문자의 경우에도)를 이스케이프할 필요가 없다는 점은 주목할 가치가 있습니다 .

    또한 이 c명령과 관련하여 같은 줄에 새 텍스트를 포함하는 것은 c\GNU 확장이며 이식성이 없다는 점에 주목할 가치가 있습니다.


s이 모든 것을 종합하면 다음과 같은 명령을 사용할 수 있습니다 .

sed -i 's:"\.\./\.\./\.\./Plumed\.h":"/usr/local/include/Plumed.h":g' ../dist0.xvg

또는 좀 더 명확하게 하고 싶다면 앵커 정규식과 change 명령을 사용하여 전체 줄을 변경할 수 있습니다.

sed -i '\:^#include "\.\./\.\./\.\./Plumed\.h"$:c\#include "/usr/local/include/Plumed.h"' ../dist0.xvg

답변2

/구분 기호 로 사용하는 경우 sed해결책은 다음과 같습니다.

sed -i 's/..\/..\/..\/Plumed.h/\/usr\/local\/include\/Plumed.h/g' file

또는 와 다른 구분 기호를 사용할 수 있습니다 . /예를 들면 다음과 같습니다.:

sed -i 's:../../../Plumed.h:/usr/local/include/Plumed.h:g' file

또 다른 방법 awk:

awk '{ gsub("../../../Plumed.h","/usr/local/include/Plumed.h"); print $0}' file

답변3

이 명령은 나에게 효과적입니다.

     sed -i 's#include "../../../Plumed.h"#include "/usr/local/include/Plumed.h"#g'

답변4

텍스트에 슬래시가 많으면 느낌표를 사용하세요.

sed -e 's!../../../Plumed.h!/usr/local/include/Plumed.h!'

관련 정보