Hinzufügen einer Wertespalte in einer tabulatorgetrennten Datei

17

Wie kann ich einer Datei mit einer bestimmten Anzahl von Zeilen eine Spalte mit Werten hinzufügen? Ich habe eine Eingabedatei wie diese:

Eingabedatei:

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

Ausgabedatei:

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 diesem Fall möchte ich eine Spalte mit Werten bis zur Anzahl der Zeilen in der Datei hinzufügen. Der Wert bleibt konsistent, z. B. "file1".

Der Grund ist, dass ich 100 dieser Dateien habe. Ich möchte nicht jede Datei öffnen und eine Spalte einfügen. Es gibt auch eine Möglichkeit, dies zu automatisieren, indem Sie in ein Verzeichnis gehen und eine Spalte mit Werten hinzufügen. Der Wert stammt aus dem Dateinamen, der in jeder Zeile der Datei in der letzten / ersten Spalte hinzugefügt werden muss.

Ron
quelle

Antworten:

22

Sie können eine Einzeiler-Schlaufe wie folgt verwenden:

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

Für jede Datei in der Liste werden sedam Ende jeder Zeile ein Tabulator und der Dateiname angehängt.

Erläuterung:

  • Verwenden Sie das -iFlag mit sed, um einen direkten Austausch durchzuführen und die Datei zu überschreiben
  • Ersetzen Sie mit s/PATTERN/REPLACEMENT/. In diesem Beispiel ist PATTERN $das Zeilenende und REPLACEMENT ist \t(= ein TAB) und $fder Dateiname der Schleifenvariablen. Der s///Befehl steht in doppelten Anführungszeichen, damit die Shell Variablen erweitern kann.
janos
quelle
Der Code funktioniert. Können Sie den Inhalt in Anführungszeichen erklären?
Ron
Genau wie "awk" beim Arbeiten mit Spalten verwendet wird, wird "sed" auch für ähnliche Situationen verwendet. Ich bin Neuling in "awk" und "sed".
Ron
@Ron sedeignet sich am besten zum Ersetzen und Speichern von Mustern. Für Ihre Anforderung, die Datei zu speichern, war dies eine relativ bequeme Option. Wenn Sie nicht in dieselbe Datei zurückschreiben müssen, die Sie gerade bearbeiten, awkist die Arbeit mit dieser Datei in der Regel viel einfacher.
Janos
Persönlich stolpere ich awkzu oft über die Eingabe- / Ausgabefeldtrennzeichen und versuche daher, sie möglichst nicht zu verwenden, um sedsie attraktiver zu machen.
user5359531
11

Komm schon, warum ihr diese mächtigen Werkzeuge empfiehlt, wenn es pasteBefehl gibt!

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

Mit ein wenig Trick könnten Sie pastefür den Zweck des OP verwenden. Die vorhandenen Dateien werden jedoch nicht ersetzt:

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

Dadurch wird der jeweilige Dateiname als letzte Spalte jeder Datei in eine neue Datei eingefügt filename.new

Yegle
quelle
Vielen Dank! pasteist sicherlich ein verstecktes Juwel.
Neu242
10

Sie können verwenden awk:

awk '{print $0, FILENAME}' file1 file2 file3 ...
cuonglm
quelle
Da jede Datei einen anderen Namen hat, muss ich dies 100 Mal tun. Gibt es eine Möglichkeit, dies einmal zu tun?
Ron
Nein, FILENAMEist eine Variable in awk, wird auf den aktuellen Dateinamen erweitert, der awkgerade verarbeitet wird. Du machst es einfach einmal, füttere alle Dateien an awk.
Donnerstag,
ok, aber wie leite ich die Ausgabe in eine neue Datei jeder Datei? Speichert awk die einzelnen Dateien während der Verarbeitung?
Ron
Wenn Sie haben GNU awk 4.1.0oder später, können Sie verwenden -i, um an Ort und Stelle zu bearbeiten. Andernfalls sollten Sie die awkAusgabe in eine temporäre Datei umleiten und dann grepzum Extrahieren der Zeilen aus den einzelnen Dateien verwenden.
Cuonglm
Nun, Sie können tunfor file in *; do awk 'BEGIN{OFS="\t"}{print $0, FILENAME}' $file; done
Fedorqui