En Bash, ¿cómo agrego una cadena después de cada línea en un archivo?

112

¿Cómo agrego una cadena después de cada línea en un archivo usando bash? ¿Se puede hacer usando el comando sed? Si es así, ¿cómo?

Jason Volkoz
fuente

Respuestas:

188

Si su sedpermite la edición en el lugar a través del -iparámetro:

sed -e 's/$/string after each line/' -i filename

Si no es así, tienes que hacer un archivo temporal:

typeset TMP_FILE=$( mktemp )

touch "${TMP_FILE}"
cp -p filename "${TMP_FILE}"
sed -e 's/$/string after each line/' "${TMP_FILE}" > filename
Tom DeGisi
fuente
¿Por qué tienes touchel archivo temporal? Y sedcondicionaría el comando al éxito del cpo podría perderse el original.
Pausado hasta nuevo aviso.
Toqué el archivo para reservar rápidamente el nombre temporal. Puede que esto no sea necesario. Creo que tiene razón al hacer que el comando sed esté condicionado al éxito de cp. ¿Por qué no editar el código para hacer esa corrección? ¡No me importará un poco! Tuyo, Tom
Tom DeGisi
¿Qué hay de agregar una cadena antes de una línea?
Oxwivi
10
@Oxwivi: sed -e 's/^/string after each line/' -i filename $ significa fin de línea. ^ significa comienzo de línea.
Tom DeGisi
Si estoy entrando en sed, sed 's/^/string after each line/'hace lo que esperaría (antepone a cada línea) pero sed 's/^/string after each line/'no (reemplaza toda la línea con mi cadena de anexión). ¿Lo que da? ¿Alguna idea @TomDeGisi?
philadams
17

Prefiero usar awk. Si solo hay una columna, use $0, de lo contrario reemplácela con la última columna.

De una sola mano,

awk '{print $0, "string to append after each line"}' file > new_file

o esto,

awk '$0=$0"string to append after each line"' file > new_file
Optimus Prime
fuente
1
Además, para agregar números de línea (como fue en mi caso), se puede usar la NRvariable:awk '{print $0, NR}'
andrybak
2
@optimus He probado su método, pero obteniendo un espacio extra para ellos, ¿alguna idea sobre cómo eliminarlos?
Adil Saju
@AdilSaju sed 's/ //g'esto funcionó para mi requisito, pero eliminará espacio en cada línea, esa es la opción gpara y en todas partes en una línea.
Eklavyaa
@AdilSaju por favor agregue detalles. Es mejor hacer una nueva pregunta.
Optimus Prime
@AdilSaju awk Eliminar me , gusta {print $0"string to append after each line"}.
Culip
8

Si lo tiene, la utilidad lam (laminado) puede hacerlo, por ejemplo:

$ lam filename -s "string after each line"
martin clayton
fuente
4
  1. Cáscara POSIX pura y sponge:

    suffix=foobar
    while read l ; do printf '%s\n' "$l" "${suffix}" ; done < file | 
    sponge file
  2. xargsy printf:

    suffix=foobar
    xargs -L 1 printf "%s${suffix}\n" < file | sponge file
  3. Usando join:

    suffix=foobar
    join file file -e "${suffix}" -o 1.1,2.99999 | sponge file
  4. Herramientas Shell usando paste, yes, head y wc:

    suffix=foobar
    paste file <(yes "${suffix}" | head -$(wc -l < file) ) | sponge file

    Tenga en cuenta que pasteinserta un carácter Tab antes $suffix.

Por supuesto, spongese puede reemplazar con un archivo temporal, luego mv'd sobre el nombre del archivo original, como con algunas otras respuestas ...

agc
fuente
1
Ninguno de estos es preferible sed, a menos que los recursos sean muy limitados.
AGC
Me gusta la solución sin sed. sedno es necesario para un trabajo tan sencillo.
Bruce
1

Yo prefiero echo. usando puro bash:

cat file | while read line; do echo ${line}$string; done
欢乐 的 Xiaox
fuente
-9

Sed es un poco feo, podrías hacerlo elegantemente así:

hendry@i7 tmp$ cat foo 
bar
candy
car
hendry@i7 tmp$ for i in `cat foo`; do echo ${i}bar; done
barbar
candybar
carbar
hendry
fuente
2
Falla para archivos con más líneas que el límite máximo de argumentos del shell. Prueba: cat foo | mientras lee a; haz eco de la barra $ {a}; hecho o algo así en su lugar; es un reemplazo adecuado para en la mayoría de los casos.
alex
1
También falla para líneas con espacios en ellas.
Pausado hasta nuevo aviso.
1
Er, no, no le falla a Dennis. límite máximo de argumentos de shell? Crikey, estás siendo pendente.
hendry
Sí lo hace: $ cat foo foo bar baz alex @ armitage: ~ $ for i in cat foo; haz eco de la barra $ {i}; hecho foobar barbar bazbar pero después de algunas pruebas, podría estar equivocado sobre mi razonamiento, pero Dennis tiene razón
alex
3
@hendry Sí, esto falla para las líneas con espacios en ellas, como echo "foo bar" | (for i in `cat`; do echo ${i}bar; done)que imprime 2 líneas aunque la entrada sea 1 línea foo bar(y catleer desde stdin en lugar de un archivo no hace ninguna diferencia en esto).
Hyde