Tengo todos los comandos de reemplazo en un archivo (por ejemplo, reemplazar.sed) y lo uso con el indicador -f de sed (sed -f reemplazar.sed InputFile). Pero ahora me encontré con una condición en la que necesito aplicar estas reglas de reemplazo solo en líneas pares de un archivo de entrada determinado (es decir, solo en las líneas 2,4,6, etc.). No puedo poner ninguna declaración de condición en reemplazo. .sed, ya que también lo utilizan otros scripts.
Respuesta1
Utilice la sustitución de procesos para adaptar los sed
comandos en su archivo sobre la marcha:
$ cat replace.sed
s#foo#bar#
.
$ printf "foo\nfoo\nfoo\nfoo\n" | sed -f replace.sed
bar
bar
bar
bar
.
$ printf "foo\nfoo\nfoo\nfoo\n" | sed -f <(sed 's#^#2~2#g' replace.sed)
foo
bar
foo
bar
Respuesta2
sed -f <(sed -e 's/.*/2~2{&;}/' replace.sed) InputFile
Respuesta3
Lo que las otras respuestas te dicen que intentas decirte es que utilices sed
el formulario de dirección:first~step
Direcciones
… Se admiten los siguientes tipos de direcciones: …
primero~pasoCombina cadapaso'ésima línea que comienza con la líneaprimero. Por ejemplo, "
sed -n 1~2p
" imprimirá todas las líneas impares en el flujo de entrada y la dirección "2~5
" coincidirá con cada quinta línea, comenzando con la segunda. primeropuede ser cero; en este caso,sed
opera como si fuera igual a paso. (Esta es una extensión).
La solución obvia sería anteponer cada comando replace.sed
con 2~2
(o 0~2
, si funciona en su versión de sed
) para que los comandos funcionen en cada dos líneas, comenzando con la segunda (es decir, todas las líneas pares en el flujo de entrada, como usted pidió). Pero dices que no puedes modificar replace.sed
. Bueno, el siguiente paso (como se identifica, pero no se explica, en las otras respuestas) es crear un archivo temporal transitorio con el shellSustitución de procesoscapacidad, donde actúa como un archivo que es la salida de . Si, como sugiere su pregunta, es solo una secuencia de comandos sustitutos simples, entonces
<(command_list)
command_list
replace.sed
sed -f <(sed 's/^/2~2/g' replace.sed)
Deberia trabajar.
Pero esto tiene inconvenientes:
- Si tiene varios comandos por línea, lo anterior afectará solo al primer comando de cada línea.
- Si tiene comandos con direcciones numéricas (por ejemplo,
42s/Zaphod/Beeblebrox/
), se convertirán, por ejemplo, en2~242…
, con la consecuencia obvia. - Y si tiene comandos con direcciones no numéricas (por ejemplo,
/windows/s/command/cmd/
), lo anterior fallará por completo.
Si se aplica alguno de estos casos, debe utilizar el
sed -f <(sed -e 's/.*/2~2{&;}/' replace.sed)
variación para poner todos los sed
comandos en cada línea en un grupo de comandos.
Pero incluso esto fallará si replace.sed
tiene comandos de varias líneas.
Sobre la base de las ideas anteriores, se me ocurrió
sed -f <(echo '0~2{'; cat replace.sed; echo '}')
que pone elcompleto replace.sed
archivo en un grupo de comandos. En mis pruebas superficiales, esto parece abordar las preocupaciones que planteé con las otras soluciones. No me sorprendería que tuviera problemas con replace.sed
comandos muy largos o muy complejos.