ファイルの古い文字列と新しい文字列の両方を使用してファイル内の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);
    */

したがって、この行を2つのファイルに入れ、sedを使用して自動的に置き換えを行います。ところがインターネットで検索した結果、やっと見つけました。sedを使用して文字列をファイルの内容に置き換えるそしてsed - 文字列をファイルの内容に置き換えるつまり、ソースまたはターゲットスキーマだけが1つのファイルにあり、残りはオンラインファイルにあることを意味します。ただし、ファイルには両方のサンプルがありません。

それでは、交換する方法は何ですか? 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. コマンドを使用してパッチファイルを作成します。

2つのファイルがあり、そのうちの1つに置き換えたいブロックが含まれているとします。

$ 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);
*/

関連情報