Ejemplo, tengo un archivo con el siguiente contenido:
eggs
bacon
cereal
eggs
bacon
cheese
cereal
Producción:
eggs
bacon
cereal
En el ejemplo, quiero eliminar líneas entre las palabras eggs
y cereal
, pero solo si contiene cheese
algo intermedio.
¿Cómo podría hacer esto usando sed
?
Me pidieron que fuera más específico, así que esto es básicamente lo que quiero hacer, y espero que esto quede más 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 es el comando que probé:
sed '/"crosshair"/,/}/d' file.txt
Ese comando simplemente elimina desde el primero "crosshair"
hasta el último }
, independientemente de si tiene la línea "sprites/crosshairs"
intermedia o no.
Solo quiero eliminar de "crosshair"
a }
si entre los patrones "sprites/crosshairs"
se encuentra la cadena. Sin embargo, hay otros bloques de código en el archivo de texto que contiene "sprites/crosshairs"
.
Como:
"autoaim"
{
"file" "sprites/crosshairs"
"x" "0"
"y" "48"
"width" "24"
"height" "24"
}
Esto no se puede eliminar. Pido disculpas PROFUNDAMENTE por no haber explicado esto antes, pero no pensé que fuera necesario.
La sugerencia de don_crissti funciona bastante bien, lo cual essed '/crosshair/,/\}/{H;/\}/!d;s/.*//;x;/sprites\/crosshairs/d;s/.//;}' infile
Sin embargo, el resultado es este:
... "autoaim" { } }
"autoaim"
se eliminó parcialmente, pero no por completo, pero como puede ver, el bloque que contiene "sprites/crosshairs"
se eliminó, como quería hacer, pero autoaim
aún no se puede modificar.
Respuesta1
sed '/^[[:blank:]]*"crosshair"/,/}/{H;/}/!d;s/.*//;x;/sprites\/crosshairs/d;s/.//;}' infile
Cómo 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
Esto supone que las líneas coincidentes ^[[:blank:]]*"crosshair"
siempre van seguidas de un bloque de líneas entre llaves, como en su ejemplo.
Respuesta2
si perl
está bien, se puede usar el modo de párrafo ( -00
opción) y usar la coincidencia de expresiones regulares de varias líneas
$ cat ip.txt
eggs
bacon
cereal
eggs
bacon
cheese
cereal
$ perl -00 -ne 'print if !/^eggs.*cheese.*cereal$/ms' ip.txt
eggs
bacon
cereal