2012-04-11 22 views
16

Estoy trabajando en un bash-script que tiene que preparar un correo electrónico para enviarlo a un usuario.Reemplazar una palabra con varias líneas usando sed?

Agrega algunos datos, que terminan siendo varias líneas de cosas. Para el ejemplo almacenado en $DATA.

Ahora, después de un poco de stfw encontré algunas cosas como sed -ei "s/_data_/${DATA}/g" mail.tpl y también sed replace with variable with multiple lines. Ninguno de ellos funciona.

Ahora la pregunta es, ¿cómo consigo sed para reemplazar algo con múltiples líneas de texto?

(Alternativas a sed también son bienvenidos!)

+1

posible duplicado de [SED reemplazar con la variable con múltiples líneas] (http://stackoverflow.com/questions/6684487/sed-replace-with-variable-with-multiple-lines) –

+1

@ZsoltBotykai ¿No dices? : D Incluso lo mencioné en mi pregunta ... –

Respuesta

10

Si se construye el texto de varias líneas con "\n" s, esto va a funcionar con un simple comando de sed como:

DATA=`echo ${DATA} | tr '\n' "\\n"` 
#now, DATA="line1\nline2\nline3" 
sed "s/_data_/${DATA}/" mail.tpl 
+0

Obtengo 'sed: -e expresión # 1, char 32: comando 's' sin terminación 'de ese método. –

+1

Vaya, no vi su edición. ¡Esto realmente funciona! –

+1

Esto no es completamente portátil; no todos los dialectos 'sed' aceptan el dígrafo' \ n' para representar una nueva línea literal. En algunos otros dialectos, es probable que necesite usar una barra invertida antes de una nueva línea literal. Otras respuestas en esta página le muestran cómo hacerlo con más detalle. – tripleee

8

awk?

kent$ cat test 
foo 
bar 
blah _data_and_data_ 
foo 
_data_ foobar _data_ again 


kent$ echo $DATA 
1 
2 
3 
4 
5 

kent$ awk -v r=$DATA '{gsub(/_data_/,r)}1' test 
foo 
bar 
blah 1 
2 
3 
4 
5and1 
2 
3 
4 
5 
foo 
1 
2 
3 
4 
5 foobar 1 
2 
3 
4 
5 again 
+1

¡Dios mío, esto funciona! Desearía poder hacerte +1 varias veces más, ¡me salvaste hombre! –

+2

Hola Kent, este es uno antiguo, pero parece que te faltan citas sobre $ DATA. ¿confirmar? –

+0

debe agregar citas de hecho: awk -vr = "$ DATA" '{gsub (/ _ data _ /, r)} 1' test –

7

Lo probé y sed 's/pattern/\na\nb\nc/g' pero no funciona en todos los sistemas . Lo que funciona es poner un \ seguido de una nueva línea en el patrón de sustitución, así:

sed 's/pattern/a\ 
b\ 
c/g' 

Esto añade una línea que contiene b y una línea que contiene c cuando se ve el patrón.

Para ponerlo en una variable, utilice barras invertidas dobles:

export DATA="\\ 
a\\ 
b\\ 
c" 

y luego:

sed "s/pattern/${DATA}/g" 

Nota las comillas dobles.

0

Usted puede poner sus datos en un archivo temporal y ejecute:

$ sed '/_data_/r DATA_FILE' mail.tpl | sed '/_data_/d'> temp; mv temp mail.tpl 
+0

Eso es una solución en el mejor de los casos. – tripleee

7

que sugeriría una simple sustitución sed con el Perl orden como la siguiente: Respuesta

perl -i.bak -pe 's/_data_/'"${DATA}"'/g' mail.tpl 
+1

Esto es lo único que funcionó para mí en OSX. Todos los otros enfoques basados ​​en sed y awk fallaron en mí. –

5

del portador del anillo no funcionó para yo; Creo que el uso de tr es incorrecto, y la forma en que está escrito, simplemente elimina las líneas nuevas mediante el uso de echo.

En su lugar, he usado sed. Utilicé el código de another answer para reemplazar las nuevas líneas (crédito: Zsolt Botykai). También esperaba algunos signos de dólar ($) en mi entrada, así que me ocupé de eso también. Es posible que necesite agregar otro manejo de entrada. Tenga en cuenta el uso de comillas dobles en echo para conservar líneas nuevas.

DATA="$(cat whatever)" 
ESCAPED_DATA="$(echo "${DATA}" | sed ':a;N;$!ba;s/\n/\\n/g' | sed 's/\$/\\$/g')" 

continuación, puede utilizar ${ESCAPED_DATA} en sed:

cat input | sed 's/one liner/'"${ESCAPED_DATA}"'/' > output 

Sólo pensé en compartir.

+0

Esto funciona bien también cuando se han construido cadenas de varias líneas en un script 'bash' con el constructo' $ '\ n'' (el 'cat' al principio, por supuesto, no es necesario ya que el string ya está en una variable). – Ville

1

Variable de eco en archivo de texto temporal.

archivos Insertar texto en mail.tpl y borrar los datos de mail.tpl

echo ${DATA} > temp.txt  
sed -i -e "/_data_/r temp.txt" -e "//d" mail.tpl 
0

No estoy seguro si usted ha tratado de poner "\ n" en el sustituir parte

sed 's/[pattern]/\ 
[line 1]\n\ 
[line 2]\n\ 
[line n]\n\ 
/g' mail.tpl 

La primera línea tiene/\ por razones de legibilidad. Cada línea después de eso es una línea independiente como la que encontrarías en un editor de texto. La última línea es independiente, una vez más por razones de legibilidad. Puede hacer todo esto una línea si es necesario. Funciona en Debian Jessie cuando lo probé.

0

Escapar de todas las líneas nuevas con \ (excepto la última) funcionó para mí. La última nueva línea no se debe escapar para no romper el comando s.

Ejemplo:

DATA="a 
b 
c" 

ESCAPED=$(echo "${DATA}" | sed '[email protected][email protected]\\@g') 
echo "${ESCAPED}" 
a\ 
b\ 
c 

sed "s/pattern/${ESCAPED}/" file 
Cuestiones relacionadas