たとえば、次の内容を含むファイルがあります。
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