Usando un documento aquí para `sed` y un archivo

10

Quiero usar un documento here-doc para comandos sed y proporcionar el archivo que se leerá y el archivo de salida.

He visto Here-Documents de la guía Advanced Bash Scripting, pero no menciona nada sobre argumentos regulares al usar un here-doc. ¿Es posible?

Me gustaría lograr algo como lo siguiente:

#!/bin/bash
OUT=/tmp/outfile.txt
IN=/my_in_file.txt

sed $IN << SED_SCRIPT
    s/a/1/g
    s/test/full/g

SED_SCRIPT 
> $OUT;

Cualquier ayuda es muy apreciada.

Tristiano
fuente

Respuestas:

14

Puede decirle a GNU sed que lea el script desde una entrada estándar -f -, -flo que significa leer el script desde un archivo y -significa entrada estándar como es común con muchos comandos.

sed -f - "$IN" > "$OUT" << SED_SCRIPT
    s/a/1/g
    s/test/full/g
SED_SCRIPT

POSIX sed también es compatible -f, pero el uso de -la entrada estándar no está documentado. En este caso, podría usarlo /dev/stdinen sistemas Linux (y creo recordar que Solaris también tiene esto, pero no puedo confirmarlo en este momento)

El uso <<-SED_SCRIPT(con el prefijo '-') permitirá sangrar la SED_SCRIPTetiqueta de cierre .

camh
fuente
Gracias, lo que dijo funcionó, cómo quisiera señalar que el token de cierre no puede sangrarse, de lo contrario, causa un error en bash, supongo que esto se debe a que también incluye el espacio en blanco en el cierre.
Tristian
Tenga en cuenta que Apple OS X sed no admite la lectura de un script desde la entrada estándar. (Al menos no de esa manera ni de ninguna otra manera documentada.)
danorton
@danorton: He añadido una solución que no requiere el apoyo de -f -en sedpero requiere la sustitución de proceso: <( command ).
pabouk
5

En caso de que sedno soporta la lectura de un guión de stdin(usando -f -), puede utilizar la sustitución de proceso (disponible en bash, zsh, ksh93):

sed "$IN" > "$OUT" -f <( cat << SED_SCRIPT
    s/a/1/g
    s/test/full/g
SED_SCRIPT)

El paréntesis de cierre )debe seguir al delimitador final ( SEC_SCRIPT) inmediatamente o después de una nueva línea. En el caso de la sustitución de procesos, también puede usar en echolugar de un documento aquí:

sed "$IN" > "$OUT" -f <( echo \
"    s/a/1/g
    s/test/full/g" )
pabouk
fuente
1
En Mac OS X, no le gustaba el archivo de entrada ( "$IN"o incluso testfile.txt) inmediatamente después del comando sed en sí mismo; quería un -e scripto -f file. Reorganizar la respuesta de @pabouk funcionó para mí:sed -f <( cat << ETC ... ETC) "$IN" > "$OUT"
Stephen P
En Max OSX con bash 4.2.45 y estándar BSD sed, los paréntesis de cierre tenían que estar en una nueva línea debajo del cierre SED_SCRIPT.
Alexander Klimetschek
-1

Quizás un mejor enfoque:

OUT=/dev/stdout

IN=my_in_file.txt
sed -s 's/in/out/' < $IN > $OUT
  -or-
sed -s 's/in/out/' > $OUT < $IN

IN=my_in_text
sed -s 's/in/out/' <<< $IN > $OUT
  -or-
sed -s 's/in/out/' > $OUT <<< $IN

:)

Magnus
fuente
1
Interesante, pero además del punto. El OP quiere pasar comandos sed a través de stdin.
muru
Este enfoque permite ambos métodos, ¿por qué el voto negativo?
Magnus
Repita: "pasar comandos sed a través de stdin". Su respuesta no hace eso por ningún método.
muru