Aggiunta di una colonna di valori in un file delimitato da tabulazioni


17

Come posso aggiungere una colonna di valori in un file che ha un certo numero di righe. Ho un file di input come questo:

File di input:

SPATA17 1   217947738
LYPLAL1 1   219383905
FAM47E  4   77192838
SHROOM3 4   77660162
SHROOM3 4   77660731
SHROOM3 4   77662248

File di uscita:

SPATA17 1   217947738 file1
LYPLAL1 1   219383905 file1
FAM47E  4   77192838  file1
SHROOM3 4   77660162  file1
SHROOM3 4   77660731  file1
SHROOM3 4   77662248  file1

In questo caso, voglio aggiungere una colonna di valori, fino al numero di righe nel file. Il valore rimane coerente, come "file1".

Il motivo è che ho 100 di quei file. Non voglio aprire ogni file e incollare una colonna. Inoltre c'è un modo per automatizzare questo, andando in una directory e aggiungendo una colonna di valori. Il valore deriva dal nome file, che deve essere aggiunto in ogni riga del file nell'ultima / prima colonna.

Risposte:


22

Puoi usare un ciclo da una riga come questo:

for f in file1 file2 file3; do sed -i "s/$/\t$f/" $f; done

Per ogni file nell'elenco, verrà utilizzato sedper aggiungere alla fine di ogni riga una scheda e il nome file.

Spiegazione:

  • Utilizzo del -iflag con sedper eseguire una sostituzione sul posto, sovrascrivendo il file
  • Effettua una sostituzione con s/PATTERN/REPLACEMENT/. In questo esempio PATTERN è $, la fine della riga, e REPLACEMENT è \t(= una TAB), ed $fè il nome del file, dalla variabile loop. Il s///comando è racchiuso tra virgolette doppie in modo che la shell possa espandere le variabili.

Il codice funziona. Puoi spiegare il contenuto tra virgolette?
Ron,

Proprio come "awk" viene utilizzato mentre si lavora con le colonne, "sed" viene utilizzato anche per situazioni simili. Sono un novizio di "awk" e "sed".
Ron,

@Ron sedè molto pratico per la sostituzione dei motivi e il salvataggio sul posto. Per la tua esigenza di salvare il file era un'opzione relativamente conveniente. Se non hai bisogno di riscrivere sullo stesso file che stai elaborando, di awksolito è molto più facile lavorare con.
Janos,

Personalmente, mi inciampo awktroppo spesso nei separatori dei campi di input / output, quindi cerco di evitare di usarlo ogni volta che è possibile, rendendolo sedpiù attraente.
user5359531

11

Dai, perché ragazzi raccomandate quei potenti strumenti quando c'è il pastecomando!

$ cat a
A
B
C
D
$ cat b
1
2
3
4
$ paste a b
A   1
B   2
C   3
D   4

Con un po 'di inganno, potresti usare pasteper lo scopo del PO. Tuttavia, non sostituirà i file presenti:

for f in file1 file2 file3; do 
    paste $f <(yes $f | head -n $(cat $f | wc -l)) > $f.new
done

Ciò incollerà il rispettivo nome file come ultima colonna di ciascun file in un nuovo file filename.new


Grazie! pasteè sicuramente una gemma nascosta.
neu242,

10

Puoi usare awk:

awk '{print $0, FILENAME}' file1 file2 file3 ...

Poiché ogni file ha un nome diverso, quindi devo farlo 100 volte. Esiste un modo per farlo una volta?
Ron,

No, FILENAMEè una variabile dentro awk, si espande al nome del file corrente che awksta elaborando. Basta farlo uno, alimentare tutti i file awk.
cuonglm

ok, ma come indirizzare l'output in un nuovo file, di ogni file? awk memorizza ogni file durante l'elaborazione?
Ron,

Se hai GNU awk 4.1.0o più tardi, è possibile utilizzare -iper modificare sul posto. Altrimenti, dovresti reindirizzare l' awkoutput su un file temporaneo, quindi utilizzare grepper estrarre la linea da ciascun file.
cuonglm

Bene, puoi farlofor file in *; do awk 'BEGIN{OFS="\t"}{print $0, FILENAME}' $file; done
fedorqui
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.