파일의 이전 문자열과 새 문자열을 모두 사용하여 파일에서 sed 바꾸기

파일의 이전 문자열과 새 문자열을 모두 사용하여 파일에서 sed 바꾸기

다음과 같이 PHP 파일의 코드 블록을 자동으로 주석 처리하고 싶습니다.

원래 블록:

    //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);

새로운 주석 블록:

    /* For the production version, the following codelines are commented
       out
    //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    */

따라서 이 줄을 두 개의 파일에 넣고 sed를 사용하여 자동으로 교체를 수행하겠습니다. 그런데 인터넷으로 검색한 결과 겨우 찾았습니다.sed를 사용하여 문자열을 파일 내용으로 대체그리고sed - 문자열을 파일 내용으로 교체, 즉 소스 또는 대상 스키마만 하나의 파일에 있고 나머지는 온라인 파일에 있음을 의미합니다. 그러나 파일에는 둘 다의 샘플이 없습니다.

그렇다면 교체하는 방법은 무엇입니까? sed를 사용해야 할까요, 아니면 awk를 사용해야 할까요?

답변1

sed이 메소드 sed는 리터럴 문자열을 이해하지 못 하므로 사용하지 마십시오 (참조sed를 사용하여 정규식 메타문자를 안정적으로 이스케이프하는 것이 가능합니까?), 그러한 도구를 사용하여 awk리터럴 문자열을 이해하는 것이 실제로 가능합니다 .

GNU를 사용한 awk다중 문자 RS합계 ARGIND:

$ awk -v RS='^$' -v ORS= '
    ARGIND < 3 { a[ARGIND]=$0; next }
    s = index($0,a[1]) {
        $0 = substr($0,1,s-1) a[2] substr($0,s+length(a[1]))
    }
    { print }
' old new file
this is
the winter
    /* For the production version, the following codelines are commented
       out
    //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    */
of our
discontent

또는 다음 중 하나를 사용하십시오 awk.

$ awk '
    FNR == 1 { a[++argind]=$0; next }
    { a[argind] = a[argind] ORS $0 }
    END {
        $0 = a[3]
        if ( s = index($0,a[1]) ) {
            $0 = substr($0,1,s-1) a[2] substr($0,s+length(a[1]))
        }
        print
    }
' old new file
this is
the winter
    /* For the production version, the following codelines are commented
       out
    //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    */
of our
discontent

위의 내용은 다음 입력 파일을 사용하여 실행되었습니다.

$ head old new file
==> old <==
    //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);

==> new <==
    /* For the production version, the following codelines are commented
       out
    //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    */

==> file <==
this is
the winter
    //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
of our
discontent

답변2

patch이러한 목적으로 이 유틸리티를 사용하는 것이 좋습니다 .

diff1. 명령을 사용하여 패치 파일을 만듭니다.

두 개의 파일이 있고 그 중 하나에 교체하려는 블록이 포함되어 있다고 가정해 보겠습니다.

$ cat toreplace.txt 
    //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);

다른 하나에는 교체하려는 블록이 포함되어 있습니다.

$ cat replacewith.txt 
    /* For the production version, the following codelines are commented
       out
    //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    */

그들 사이에 상황에 따른 차이를 만들고 콘텐츠를 패치 파일에 넣습니다.

$ diff -c toreplace.txt replacewith.txt > patchfile
$ cat patchfile
*** toreplace.txt       2024-03-17 12:12:31.073270945 +0200
--- replacewith.txt     2024-03-17 12:12:45.276887865 +0200
***************
*** 1,4 ****
--- 1,7 ----
+     /* For the production version, the following codelines are commented
+        out
      //  Enable all errors
      ini_set('display_startup_errors', 1);
      ini_set('display_errors', 1);
      error_reporting(E_ALL);
+     */

2. 패치 적용

이제 이것을 원본 파일로 간주하십시오.

$ cat myfile
line before 1
line before 2
line before 3
    //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
line after 1
line after 2 
line after 3

이전에 생성한 파일을 사용하여 patch변경하려는 파일에 대해 명령을 실행할 수 있습니다.patchfile

$ patch -cb myfile patchfile
patching file myfile
Hunk #1 succeeded at 4 (offset 3 lines).
  • 깃발이 -c도착하다-c"패치 파일을 상황에 따른 차이로 해석합니다(또는 옵션이 지정된 경우 유틸리티 차이점의 출력 -C).".
    • 없기 때문에 엄격하게 요구되는 것은 아닙니다." 유틸리티는 또는 옵션에 의해 재정의 patch되지 않는 한 차이 목록의 유형을 결정하려고 시도해야 합니다 . "-c-e-n
  • 옵션 -b은 다음과 같습니다"차이점을 적용하기 전에 수정된 각 파일의 원본 내용 사본을 접미사 가 추가된 동일한 이름의 파일에 저장하십시오 .orig."
    • 백업을 생성하지 않으려면 이 플래그를 제거할 수 있습니다.

3. 검증

이제 원본 파일을 패치된 파일과 비교해 보세요.

$ diff -c myfile{.orig,}
*** myfile.orig 2024-03-17 13:00:24.936142831 +0200
--- myfile      2024-03-17 13:13:48.882669202 +0200
***************
*** 1,10 ****
--- 1,13 ----
  line before 1
  line before 2
  line before 3
+     /* For the production version, the following codelines are commented
+        out
      //  Enable all errors
      ini_set('display_startup_errors', 1);
      ini_set('display_errors', 1);
      error_reporting(E_ALL);
+     */
  line after 1
  line after 2 
  line after 3

답변3

 sed -e '1s/.*/\/* For the production version, the following codelines are commented\nout\n&/g'  -e '$s/.*/&\n*\//g'filename


output

/* For the production version, the following codelines are commented
out
  //  Enable all errors
    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
*/

관련 정보