2つのパターン間の行を削除します。ただし、その間に特定の文字列がある場合にのみ該当します。

2つのパターン間の行を削除します。ただし、その間に特定の文字列がある場合にのみ該当します。

たとえば、次の内容を含むファイルがあります。

eggs
bacon
cereal

eggs
bacon
cheese
cereal

出力:

eggs
bacon
cereal

eggsこの例では、andという単語の間の行を削除したいと思いますcereal。ただし、inが含まれている場合にのみ適用されますcheese

これを行うにはどうすればよいですかsed

もっと具体的に説明してほしいという要請を受けたので基本的にこれが私がやりたいことです。これにより、より明確になることを願っています。

WeaponData
{
    TextureData
    {
                "crosshair"
                {
                                "file"  "vgui/replay/thumbnails/"
                                "x"             "0"
                                "y"             "0"
                                "width"         "64"
                                "height"        "64"
                }
                "weapon"
                {
                                "file"          "sprites/bucket_bat_red"
                                "x"             "0"
                                "y"             "0"
                                "width"         "200"
                                "height"                "128"
                }
                "weapon_s"
                {       
                                "file"          "sprites/bucket_bat_blue"
                                "x"             "0"
                                "y"             "0"
                                "width"         "200"
                                "height"                "128"
                }

                "ammo"
                {
                                "file"          "sprites/a_icons1"
                                "x"             "55"
                                "height"    "15"
                }

                "crosshair"
                {
                    "file"      "sprites/crosshairs" <---
                    "x"     "32"
                    "y"     "32"
                    "width"     "32"
                    "height"    "32"
                }

                "autoaim"
                {
                    "file"      "sprites/crosshairs"
                    "x"     "0"
                    "y"     "48"
                    "width"     "24"
                    "height"    "24"
                }
    }
}

私が試したコマンドは次のとおりです。

sed '/"crosshair"/,/}/d' file.txt

このコマンドは、間に行があるかどうかに関係なく、最初から"crosshair"最後まで削除します。}"sprites/crosshairs"

パターン間の文字列を見つけるためにfrom "crosshair"to ifを削除したいと思います。ただし、.txtを含むテキストファイルには異なるコードブロックがあります。}"sprites/crosshairs""sprites/crosshairs"

たとえば、

"autoaim"
{
        "file"      "sprites/crosshairs"
        "x"     "0"
        "y"     "48"
        "width"     "24"
        "height"    "24"
}

これは削除できません。これについてもっと早く説明できなかったことをお詫び申し上げます。

don_crisstiの提案は非常にうまく機能しました。sed '/crosshair/,/\}/{H;/\}/!d;s/.*//;x;/sprites\/crosshairs/d;s/.//;}' infile

ただし、出力は次のようになります。

              ...
              "autoaim"
              {
  }
}

"autoaim"部分的に削除されたが完全には削除されていませんが、ご覧のとおり、埋め込みブロックは必要に応じて削除されましたが、"sprites/crosshairs"それでもautoaim変更できません。

答え1

sed '/^[[:blank:]]*"crosshair"/,/}/{H;/}/!d;s/.*//;x;/sprites\/crosshairs/d;s/.//;}' infile

仕組み:

sed '/^[[:blank:]]*"crosshair"/,/}/{         # in this range
H                                            # append each line to hold buffer
/}/!d                                        # delete it if not the end of range
s/.*//                                       # empty the pattern space
x                                            # exchanges buffers
/sprites\/crosshairs/d                       # delete pattern space if it matches
s/.//                                        # remove leading newline, autoprint
}' infile

これは^[[:blank:]]*"crosshair"、あなたの例のように、一致する行の後に常に中括弧で囲まれた行ブロックが続くと仮定します。

答え2

perl可能であれば、短絡モード(-00オプション)を使用し、複数行の正規表現一致を使用できます。

$ cat ip.txt 
eggs
bacon
cereal

eggs
bacon
cheese
cereal

$ perl -00 -ne 'print if !/^eggs.*cheese.*cereal$/ms' ip.txt 
eggs
bacon
cereal

関連情報