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,dr:

사용:

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명령을 사용하면 주소에서 대체 구분 기호를 사용할 때처럼 첫 번째 정규식 구분 기호(구분 기호로 사용되는 특이한 문자의 경우에도)를 이스케이프할 필요가 없습니다.

    또한 명령과 관련하여 동일한 줄에 새 텍스트를 포함하는 것은 GNU 확장이며 이식성이 없다는 c점을 아는 것이 좋습니다 .c\


이 모든 것을 종합하면 다음과 같은 명령을 사용할 수 있습니다 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!'

관련 정보