Exemplo, tenho um arquivo com o seguinte conteúdo:
eggs
bacon
cereal
eggs
bacon
cheese
cereal
Saída:
eggs
bacon
cereal
No exemplo, quero excluir as linhas entre as palavras eggs
e cereal
, mas apenas se contiver cheese
entre elas.
Como eu poderia fazer isso usando sed
?
Pediram-me para ser mais específico, então aqui está basicamente o que quero fazer e espero que isso deixe tudo mais claro:
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"
}
}
}
Este é o comando que tentei:
sed '/"crosshair"/,/}/d' file.txt
Esse comando apenas exclui do primeiro "crosshair"
ao último }
, independentemente de ter "sprites/crosshairs"
ou não a linha intermediária.
Eu só quero deletar de "crosshair"
para }
se entre os padrões a string "sprites/crosshairs"
for encontrada. No entanto, existem outros blocos de código no arquivo de texto contendo "sprites/crosshairs"
.
Como:
"autoaim"
{
"file" "sprites/crosshairs"
"x" "0"
"y" "48"
"width" "24"
"height" "24"
}
Isso não pode ser removido. Peço desculpas PROFUNDAS por não explicar isso antes, mas não achei que seria necessário.
A sugestão de don_crissti funciona muito bem, o que ésed '/crosshair/,/\}/{H;/\}/!d;s/.*//;x;/sprites\/crosshairs/d;s/.//;}' infile
A saída é esta, no entanto:
... "autoaim" { } }
"autoaim"
foi parcialmente excluído, mas não completamente, mas como você pode ver o bloco que contém "sprites/crosshairs"
foi removido, como eu queria fazer, mas autoaim
ainda não pode ser modificado
Responder1
sed '/^[[:blank:]]*"crosshair"/,/}/{H;/}/!d;s/.*//;x;/sprites\/crosshairs/d;s/.//;}' infile
Como funciona:
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
Isso pressupõe que as linhas correspondentes ^[[:blank:]]*"crosshair"
são sempre seguidas por um bloco de linhas entre colchetes, assim como no seu exemplo.
Responder2
se perl
estiver tudo bem, pode-se usar o modo de parágrafo ( -00
opção) e usar a correspondência de regex multilinha
$ cat ip.txt
eggs
bacon
cereal
eggs
bacon
cheese
cereal
$ perl -00 -ne 'print if !/^eggs.*cheese.*cereal$/ms' ip.txt
eggs
bacon
cereal