删除 2 个模式之间的行,但前提是中间有特定的字符串

删除 2 个模式之间的行,但前提是中间有特定的字符串

例如,我有一个包含以下内容的文件:

eggs
bacon
cereal

eggs
bacon
cheese
cereal

输出:

eggs
bacon
cereal

在示例中,我想删除单词eggsand之间的行cereal,但前提是它包含cheesein 之间。

我怎样才能使用 来做到这一点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"}if 在模式之间"sprites/crosshairs"找到字符串。但是,包含 .txt 的文本文件上还有其他代码块"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

相关内容