Aggiungi una stringa di prefisso all'inizio di ogni riga


334

Ho un file come di seguito:

line1
line2
line3

E voglio ottenere:

prefixline1
prefixline2
prefixline3

Potrei scrivere una sceneggiatura di Ruby, ma è meglio se non ne ho bisogno.

prefixconterrà /. È un percorso, /opt/workdir/per esempio.

Risposte:


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

Se prefixcontiene /, puoi usare qualsiasi altro personaggio non presente prefixo sfuggire a /, così il sedcomando diventa

's#^#/opt/workdir#'
# or
's/^/\/opt\/workdir/'

1
@benjamin, avevo già votato a favore della tua risposta, tuttavia, preferisco sedcompiti leggeri come questo. Se si conosce "prefisso", è molto facile scegliere un carattere non da "prefisso".
Alok Singhal,

1
Non dimenticare che puoi anche usarlo sedin una pipeline, ad es foo | sed -e 's/^/x /' | bar.
zigg

1
@Dataman cool. Un altro modo sarebbe sed -e '2,$s/^/prefix/'.
Alok Singhal,

1
@BinChen escape the /like \/(in stringhe tra virgolette singole) o \\/(in stringhe tra virgolette doppie)

8
Utilizzare sed -e 's/$/postfix/' filese si desidera aggiungere una stringa alla fine di ogni riga.
Brian,

121
awk '$0="prefix"$0' file > new_file

Con Perl (sostituzione sul posto):

perl -pi 's/^/prefix/' file

8
Con una pipe / stream o variabile:prtinf "$VARIABLE\n" | awk '$0="prefix"$0'
ThorSummoner,

2
Con un file di grandi dimensioni (12 G), awksegnala awk: out of memory in readrec 1 source line number 1, ma la soluzione viene sedcompletata correttamente.
jrm,

33

Puoi usare Vim in modalità Ex:

ex -sc '%s/^/prefix/|x' file
  1. % seleziona tutte le righe

  2. s sostituire

  3. x salva e chiudi


1
Per me, apro il file in vim e digito :%s/^/prefix/, poiché questa strategia finisce per essere utile in molte situazioni
Frank Bryce,

23

Se il tuo prefisso è un po 'complicato, basta inserirlo in una variabile:

prefix=path/to/file/

Quindi, passi quella variabile e permetti a awk di gestirla:

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


6

Usando la shell:

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

5

Ecco una soluzione oneliner altamente leggibile usando il tscomando di moreutils

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

E come viene derivato passo dopo passo:

# 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

'ts' non è installato di default su molte distro Linux. Inoltre, il downvoting perché il triling "tr -d" in questa risposta rimuoverà tutti gli spazi dalle linee, non solo lo spazio che è stato aggiunto da "ts"
Tim Bird,

3

Anche se non credo che Pierr avesse questa preoccupazione, avevo bisogno di una soluzione che non ritardasse l'output della "coda" di un file dal vivo, poiché volevo monitorare simultaneamente più registri di allerta, anteponendo a ciascuna riga il nome del rispettivo registro .

Sfortunatamente, sed, cut, ecc. Hanno introdotto troppi buffering e mi hanno impedito di vedere le linee più attuali. Il suggerimento di Steven Penny di usare l' -sopzione di nlera intrigante e i test hanno dimostrato che non introduceva il buffering indesiderato che mi riguardava.

Ci sono stati un paio di problemi con l'uso nl, tuttavia, legati al desiderio di eliminare i numeri di riga indesiderati (anche se non ti interessa l'estetica di esso, potrebbero esserci casi in cui l'uso delle colonne extra sarebbe indesiderabile). Innanzitutto, l'uso di "cut" per eliminare i numeri reintroduce il problema di buffering, quindi si rovina la soluzione. In secondo luogo, l'uso di "-w1" non aiuta, dal momento che questo NON limita il numero di riga a una singola colonna, ma si allarga appena sono necessarie più cifre.

Non è carino se vuoi catturarlo altrove, ma dato che è esattamente quello che non avevo bisogno di fare (tutto era già stato scritto per registrare i file, volevo solo guardarne diversi contemporaneamente in tempo reale), il migliore modo per perdere i numeri di riga e avere solo il mio prefisso era quello di iniziare il -s stringa con un ritorno a capo (CR o ^ M o Ctrl-M). Quindi per esempio:

#!/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}

1
utilizzare l' -uopzione per sed per evitare il buffering.
Bryan Larsen,

2
Il buffering può essere disattivato con unbuffer / stdbuf, vedi unix.stackexchange.com/q/25372/6205
myroslav

2

Utilizzando ed:

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

Questo sostituisce, per ogni riga ( ,), l'inizio della riga ( ^) con prefix.wqsalva ed esce.

Se la stringa di sostituzione contiene una barra, possiamo invece utilizzare un delimitatore diverso per s:

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

Ho citato il delimitatore here-doc EOE("end of ed") per impedire l'espansione dei parametri. In questo esempio, funzionerebbe anche senza virgolette, ma è buona norma prevenire sorprese se mai ne hai uno $nello script.


2

Usando & (l'intera parte dell'input che è stata abbinata al modello ”):

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

OPPURE utilizzando i riferimenti posteriori:

cat in.txt | sed -e "s/\(.*\)/prefix\1/" > out.txt

2
  1. È inoltre possibile ottenere ciò utilizzando la tecnica di backreference

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. Puoi anche usare con awk in questo modo

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

1

Ecco un esempio completo usando il sed approccio da questa risposta :

$ 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

2
Questo non funzionerà se PREFIXcontiene caratteri speciali per sed come una barra.
Jos

Buon punto ... Se ti accorgi che usi slash molto, potresti usare un delimitatore diverso con la parte sed, come dettagliato qui , che ti permetterebbe di usarlo nelle ricerche. Altri caratteri speciali di sed possono essere inseriti scappando con una barra, ad es.prefix_lines \*
Brad Parks

0

Per le persone su sistemi BSD / OSX c'è un'utilità chiamata lam, abbreviazione di laminato. lam -s prefix filefarà quello che vuoi. Lo uso nelle condutture, ad esempio:

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

... che troverà tutti i file, eseguirli su ciascuno di essi, dando a ciascun file un prefisso del proprio nome file. (E pompare l'uscita su fzf per la ricerca.)


Hai ragione, sembra che questo sia un comando solo BSD. POSIX lo ha sostituito con incolla, ma incolla non ha la funzione di aggiungere una stringa di separazione completa. Aggiornerò la mia risposta.
Ray,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.