¿Cuál es la forma más fácil de agregar una cadena al comienzo de cada línea del archivo desde la línea de comando?

8

Estoy buscando una manera de agregar alguna cadena al comienzo de cada línea (misma cadena para cada línea). No es algo personalizable, sino algo que será fácil de recordar y estará disponible en todas las plataformas compatibles con POSIX (y también en cada shell).

sintagma
fuente

Respuestas:

8

Puedes usar sed:

sed -i 's/^/your_string /' your_file

Gracias a los comentarios de Stephane y Marco, tenga en cuenta que la -iopción no es POSIX. Una forma POSIX de hacer lo anterior sería

sed 's/^/your_string /' your_file > tmp_copy && mv tmp_copy your_file

o perl:

perl -pi -e 's/^/your_string /' your_file

Explicación

Ambos comandos realizan una sustitución de expresiones regulares, reemplazando el comienzo de una línea ( ^) con la cadena deseada. El -iinterruptor en ambos comandos asegura que el archivo se edite en su lugar (es decir, los cambios se reflejan en el archivo en lugar de imprimirse en stdout).

seddebería estar disponible en cualquier sistema operativo compatible con POSIX y perldebería estar disponible en la mayoría de los Unices modernos, excepto quizás en aquellos que se han esforzado por eliminarlo.

Joseph R.
fuente
1
Pequeña corrección: el -iinterruptor no edita el archivo en su lugar. Crea un nuevo archivo y sobrescribe el original una vez hecho (prueba: el inodo cambia). No hay muchas herramientas que realmente realicen la edición in situ, lo cual es una operación peligrosa. Además, dado que menciona POSIX, el -icambio no es obligatorio para un POSIX compatible sed, es una característica de algunas implementaciones particulares.
Marco
2
sed -iNo es POSIX. Es GNU. FreeBSD sedtiene una opción similar, pero la necesitas sed -i ''allí.
Stéphane Chazelas
@Marco, sé que -icrea una copia temporal (por eso dije que los cambios se reflejan en el archivo original); Quise decir que obtienes la misma semántica que la sustitución in situ. Verifique que la respuesta actualizada sea compatible con POSIX.
Joseph R.
Estrictamente hablando, los cambios se reflejan en un nuevo archivo con el mismo nombre que el original.
Keith Thompson
1
A menudo uso $$(la identificación de proceso del shell actual) como parte de un nombre de archivo temporal; evita el esfuerzo de pensar en un nombre único garantizado cada vez:command filename > filename.$$ && mv filename.$$ filename
Keith Thompson
14
:|paste -d'foo ' - - - - input > output

(es broma, aunque probablemente encontrará que es la más rápida de todas las soluciones publicadas aquí: -b).

La forma canónica es:

sed 's/^/foo /' < input > output

Sin embargo, no se adapta fácilmente a cadenas arbitrarias. Por ejemplo,

sed "s/^/$var /"

Sólo funciona si $varno contiene, &, \, /ni los caracteres de nueva línea.

En ese sentido,

export var
awk '{print ENVIRON["var"], $0}'

o

perl -pe '$_="$ENV{var} $_"'

Funcionaría mejor.

Stéphane Chazelas
fuente
eso es algo interesante ...: P
Rahul Patil
4

awkPresento una solución usando la secuencia anterior "foo".

awk '{ print "foo", $0; }' input > output

awkes multiplataforma y está disponible en cualquier sistema POSIX. No hace edición en el lugar. Si desea editar un archivo sin crear uno segundo, deberá usar un archivo temporal. Vea la sedrespuesta de Joseph , muestra la sintaxis. Otro truco es usar la siguiente sintaxis, que básicamente es crear un archivo temporal con el mismo nombre de archivo que el archivo original.

{ rm file; awk '{ print "foo", $0 }' > file; } < file
Marco
fuente
reducto# wc -l foo`914 foo` reducto# { rm foo ; awk '{ print "prepend" , $0 }' > foo } < foo >Esto no parece funcionar. Lo intentaba porque la redirección al original me ponía nervioso, pero ni siquiera comienza.
kurtm
1
Este ejemplo funcionará si usa paréntesis para el exterior en lugar de llaves.
kurtm
4

Puede evitar los problemas de la edición in situ con las herramientas de transmisión utilizando una herramienta que normalmente realiza la edición in situ: ¡un editor!

ex sample.txt -c "%s/^/foo /" -c wq

Existe una ventaja adicional de que los comandos son fáciles y obvios para cualquiera que esté versado en el único editor verdadero.

Mike DeAngelo
fuente
2

Puedes usar perlpara hacer esto:

$ perl -pi -e 's/^/mystring /' afile.txt

Ejemplo

Crea un archivo de muestra.

$ seq 5 > afile.txt

$ cat afile.txt
1
2
3
4
5

Ejecute el comando anterior:

$ perl -pi -e 's/^/mystring /' afile.txt

$ cat afile.txt
mystring 1
mystring 2
mystring 3
mystring 4
mystring 5
slm
fuente
Perl parece ser universal hoy en día, pero durante mucho tiempo no lo fue. Y apuesto a que hay un par de variantes raras de UNIX que se niegan firmemente a tener Perl como parte de la base. Algo a tener en cuenta.
kurtm
@kurtm vea la discusión aquí . Aparentemente, AIX no tiene Perl por defecto y tampoco tiene sistemas integrados.
terdon
2
@DavidSainty: es lo suficientemente universal. La Q fue etiquetada con Bash, así que me resulta extremadamente difícil imaginar un sistema que tenga Bash pero no Perl. En cualquier caso, aquí hay una de las 5 respuestas, varias de las otras muestran cómo usarlas sed, le mostré cómo usar Perl ... sin buscar una guerra santa sobre el asunto.
slm
1
@DavidSainty Aparentemente solo OpenBSD. Supongo que hice la suposición ya que la gente de Open tiende a ser conservadora sobre lo que permiten en la base. OpenBSD definitivamente lo tiene en la base.
kurtm
1
@slm: " Me resulta extremadamente difícil imaginar un sistema que tenga Bash pero no Perl ". Tengo varios sistemas de este tipo en mi escritorio. (Resultan sistemas embebidos.)
Keith Thompson
1

Simplemente usando Bash

 while IFS= read -r line; do echo "foo" "${line}" ; done  < input > Output

Usando Python

python -c "import sys; print 'foo '.join([ l for l in sys.stdin.readlines() ])" < input > Output

Si desea editar en el lugar

import fileinput
import sys

for line in fileinput.input(['inputfile'], inplace=True):
    sys.stdout.write('foo {l}'.format(l=line))

Link de referencia

Rahul Patil
fuente
¿Por qué funciona más rápido que awk?
Rahul Patil
1
Solo funcionará más rápido que awken archivos muy pequeños. El comportamiento varía entre las implementaciones de eco y elimina espacios en blanco iniciales y finales, y procesa barras invertidas especialmente.
Stéphane Chazelas
@StephaneChazelas Sí. estás 100% correcto, acabo de probar ... paste.ubuntu.com/6210934
Rahul Patil
prefix () { while IFS= read -r REPLY; do printf "%s%s\n" "$1" "$REPLY"; done; }Debería ser más correcto.
Matt
1
¿Por qué el {}? Creo que @Matt estaba sugiriendo que lo convirtieras en una función con nombre, ¿qué sentido tiene {}sin un nombre de función?
terdon
-1

O puede hacer lo siguiente:

vi filename.txt

Esc(para asegurarte de que estás en NORMALmodo) y luego ingresa el siguiente comando:

:1,$ s/^/mystring
Dino
fuente
Tenga en cuenta que, dado que el usuario pregunta sobre cada línea del archivo, puede reemplazarlo 1,$ simplemente %. Esto hace el comando :%s/^/string/.
HalosGhost