Beispiel: Ich habe eine Datei mit folgendem Inhalt:
eggs
bacon
cereal
eggs
bacon
cheese
cereal
Ausgabe:
eggs
bacon
cereal
Im Beispiel möchte ich Zeilen zwischen den Wörtern eggs
und löschen cereal
, aber nur, wenn cheese
dazwischen steht.
Wie könnte ich dies mithilfe von tun sed
?
Ich wurde gebeten, genauer zu werden. Hier ist also im Wesentlichen, was ich tun möchte, und ich hoffe, dies macht es klarer:
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"
}
}
}
Dies ist der Befehl, den ich ausprobiert habe:
sed '/"crosshair"/,/}/d' file.txt
Dieser Befehl löscht nur vom allerersten "crosshair"
bis zum allerletzten }
, unabhängig davon, ob eine Zeile "sprites/crosshairs"
dazwischen steht oder nicht.
"crosshair"
Ich möchte nur von bis löschen }
, wenn zwischen den Mustern die Zeichenfolge "sprites/crosshairs"
gefunden wird. Es gibt jedoch andere Codeblöcke in der Textdatei, die enthalten "sprites/crosshairs"
.
Wie zum Beispiel:
"autoaim"
{
"file" "sprites/crosshairs"
"x" "0"
"y" "48"
"width" "24"
"height" "24"
}
Dies kann nicht entfernt werden. Ich entschuldige mich zutiefst dafür, dass ich dies nicht früher erklärt habe, aber ich dachte nicht, dass es notwendig wäre.
don_crissti's Vorschlag funktioniert ganz gut, das istsed '/crosshair/,/\}/{H;/\}/!d;s/.*//;x;/sprites\/crosshairs/d;s/.//;}' infile
Die Ausgabe ist jedoch diese:
... "autoaim" { } }
"autoaim"
ist teilweise gelöscht, aber nicht vollständig, aber wie Sie sehen, "sprites/crosshairs"
ist der Block, der enthält, wie ich es wollte, entfernt, kann aber autoaim
immer noch nicht geändert werden
Antwort1
sed '/^[[:blank:]]*"crosshair"/,/}/{H;/}/!d;s/.*//;x;/sprites\/crosshairs/d;s/.//;}' infile
Wie es funktioniert:
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
Dies setzt voraus, dass auf übereinstimmende Zeilen ^[[:blank:]]*"crosshair"
immer ein Block von Zeilen in Klammern folgt, genau wie in Ihrem Beispiel.
Antwort2
wenn perl
das ok ist, kann man den Absatzmodus ( -00
Option) verwenden und mehrzeilige Regex-Übereinstimmung verwenden
$ cat ip.txt
eggs
bacon
cereal
eggs
bacon
cheese
cereal
$ perl -00 -ne 'print if !/^eggs.*cheese.*cereal$/ms' ip.txt
eggs
bacon
cereal