Agregue una cadena de prefijo al comienzo de cada línea

334

Tengo un archivo de la siguiente manera:

line1
line2
line3

Y quiero obtener:

prefixline1
prefixline2
prefixline3

Podría escribir un script Ruby, pero es mejor si no lo necesito.

prefixcontendrá /. Es un camino, /opt/workdir/por ejemplo.

pierrotlefou
fuente

Respuestas:

527
# If you want to edit the file in-place
sed -i -e 's/^/prefix/' file

# If you want to create a new file
sed -e 's/^/prefix/' file > file.new

Si prefixcontiene /, puede usar cualquier otro personaje que no esté en él prefixo escapar de él /, por lo que el sedcomando se convierte en

's#^#/opt/workdir#'
# or
's/^/\/opt\/workdir/'
Alok Singhal
fuente
1
@benjamin, ya había votado tu respuesta, sin embargo, prefiero sedtareas livianas como esta. Si se conoce el "prefijo", es muy fácil elegir un personaje que no sea del "prefijo".
Alok Singhal
1
No olvide que también puede usar seden una tubería, por ejemplo foo | sed -e 's/^/x /' | bar.
zigg
1
@Dataman genial. Otra forma sería sed -e '2,$s/^/prefix/'.
Alok Singhal
1
@BinChen escapa del me /gusta \/(en cadenas de comillas simples) o \\/(en cadenas de comillas dobles)
8
Úselo sed -e 's/$/postfix/' filesi desea agregar una cadena al final de cada línea.
Brian
121
awk '$0="prefix"$0' file > new_file

Con Perl (reemplazo en el lugar):

perl -pi 's/^/prefix/' file
Vijay
fuente
8
Con una tubería / flujo o variable:prtinf "$VARIABLE\n" | awk '$0="prefix"$0'
ThorSummoner
2
Con un archivo grande (12 G), awkinformes awk: out of memory in readrec 1 source line number 1, pero la solución se sedcompleta con éxito.
jrm
33

Puede usar Vim en modo Ex:

ex -sc '%s/^/prefix/|x' file
  1. % seleccione todas las líneas

  2. s reemplazar

  3. x guardar y cerrar

Steven Penny
fuente
1
Para mí, solo abro el archivo en vim y escribo :%s/^/prefix/, ya que esta estrategia termina siendo útil en muchas situaciones
Frank Bryce
23

Si su prefijo es un poco complicado, simplemente póngalo en una variable:

prefix=path/to/file/

Luego, pasa esa variable y deja que awk se ocupe de ella:

awk -v prefix="$prefix" '{print prefix $0}' input_file.txt
Melka
fuente
11

Si tienes Perl:

perl -pe 's/^/PREFIX/' input.file
Majid Azimi
fuente
6

Usando la cáscara:

#!/bin/bash
prefix="something"
file="file"
while read -r line
do
 echo "${prefix}$line"
done <$file > newfile
mv newfile $file
ghostdog74
fuente
5

Aquí hay una solución oneliner altamente legible que usa el tscomando de moreutils

$ cat file | ts prefix | tr -d ' '

Y cómo se deriva paso a paso:

# Step 0. create the file

$ cat file
line1
line2
line3
# Step 1. add prefix to the beginning of each line

$ cat file | ts prefix
prefix line1
prefix line2
prefix line3
# Step 2. remove spaces in the middle

$ cat file | ts prefix | tr -d ' '
prefixline1
prefixline2
prefixline3
navigaid
fuente
'ts' no está instalado por defecto en muchas distribuciones de Linux. Además, el voto negativo porque el "tr -d" final en esta respuesta eliminará todos los espacios de las líneas, no solo el espacio agregado por 'ts'
Tim Bird
3

Si bien no creo que pierr tuviera esta preocupación, necesitaba una solución que no retrasara la salida de la "cola" en vivo de un archivo, ya que quería monitorear varios registros de alertas simultáneamente, con el prefijo de cada línea con el nombre de su registro respectivo .

Desafortunadamente, sed, cut, etc. introdujo demasiado buffering y me impidió ver las líneas más actuales. La sugerencia de Steven Penny de usar la -sopción de nlera intrigante, y las pruebas demostraron que no introdujo el almacenamiento en búfer no deseado que me preocupaba.

Sin nlembargo, hubo un par de problemas con el uso , relacionados con el deseo de eliminar los números de línea no deseados (incluso si no le importa la estética de la misma, puede haber casos en los que no sería deseable usar las columnas adicionales). Primero, usar "cortar" para eliminar los números reintroduce el problema de almacenamiento en búfer, por lo que arruina la solución. En segundo lugar, el uso de "-w1" no ayuda, ya que esto NO restringe el número de línea a una sola columna, simplemente se amplía a medida que se necesitan más dígitos.

No es bonito si quieres capturar esto en otro lugar, pero dado que eso es exactamente lo que no necesitaba hacer (ya se estaba escribiendo todo en los archivos de registro, solo quería ver varios a la vez en tiempo real), lo mejor La forma de perder los números de línea y tener solo mi prefijo era comenzar la -scadena con un retorno de carro (CR o ^ M o Ctrl-M). Así por ejemplo:

#!/bin/ksh

# Monitor the widget, framas, and dweezil
# log files until the operator hits <enter>
# to end monitoring.

PGRP=$$

for LOGFILE in widget framas dweezil
do
(
    tail -f $LOGFILE 2>&1 |
    nl -s"^M${LOGFILE}>  "
) &
sleep 1
done

read KILLEM

kill -- -${PGRP}
ScriptGuy
fuente
1
use la -uopción de sed para evitar el almacenamiento en búfer.
Bryan Larsen
2
El almacenamiento en búfer se puede desactivar con unbuffer / stdbuf, consulte unix.stackexchange.com/q/25372/6205
myroslav
2

Usando ed:

ed infile <<'EOE'
,s/^/prefix/
wq
EOE

Esto sustituye, para cada línea ( ,), el comienzo de la línea ( ^) con prefix. wqsalva y sale.

Si la cadena de reemplazo contiene una barra oblicua, podemos usar un delimitador diferente para s:

ed infile <<'EOE'
,s#^#/opt/workdir/#
wq
EOE

He citado el delimitador here-doc EOE("fin de ed") para evitar la expansión de parámetros. En este ejemplo, también funcionaría sin comillas, pero es una buena práctica evitar sorpresas si alguna vez tiene un $script ed.

Benjamin W.
fuente
2

Usando & (toda la parte de la entrada que coincidió con el patrón ”):

cat in.txt | sed -e "s/.*/prefix&/" > out.txt

O usando referencias posteriores:

cat in.txt | sed -e "s/\(.*\)/prefix\1/" > out.txt
Ark25
fuente
2
  1. También puede lograr esto utilizando la técnica de referencia

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. También puedes usar con awk como este

    awk '{print "prefix"$0}' foo.txt > tmp && mv tmp foo.txt
    
k_vishwanath
fuente
1

Aquí hay un ejemplo resumido usando el sedenfoque de esta respuesta :

$ cat /path/to/some/file | prefix_lines "WOW: "

WOW: some text
WOW: another line
WOW: more text

prefix_lines

function show_help()
{
  IT=$(CAT <<EOF
    Usage: PREFIX {FILE}

    e.g.

    cat /path/to/file | prefix_lines "WOW: "

      WOW: some text
      WOW: another line
      WOW: more text
  )
  echo "$IT"
  exit
}

# Require a prefix
if [ -z "$1" ]
then
  show_help
fi

# Check if input is from stdin or a file
FILE=$2
if [ -z "$2" ]
then
  # If no stdin exists
  if [ -t 0 ]; then
    show_help
  fi
  FILE=/dev/stdin
fi

# Now prefix the output
PREFIX=$1
sed -e "s/^/$PREFIX/" $FILE
Brad Parks
fuente
2
Esto no funcionará si PREFIXcontiene caracteres especiales para sed como una barra inclinada.
josch
Buen punto ... Si encuentra que usa una barra oblicua mucho, podría usar un delimitador diferente con la parte sed, como se detalla aquí , lo que le permitiría usarlo en las búsquedas. Se pueden introducir otros caracteres sed especiales escapándose con una barra, por ejemploprefix_lines \*
Brad Parks el
0

Para las personas con sistemas BSD / OSX hay una utilidad llamada lam, abreviatura de laminado. lam -s prefix fileHará lo que quieras. Lo uso en tuberías, por ejemplo:

find -type f -exec lam -s "{}: " "{}" \; | fzf

... que encontrará todos los archivos, exec lam en cada uno de ellos, dando a cada archivo un prefijo de su propio nombre de archivo. (Y bombee la salida a fzf para buscar).

Rayo
fuente
Tienes razón, parece que este es un comando solo BSD. POSIX lo reemplazó con pegar, pero pegar no tiene la característica de agregar una cadena de separación completa. Actualizaré mi respuesta.
Ray