Ich habe sieben (oder acht usw.) Dateien mit der gleichen Zeilenanzahl.
Datei1
1.001
1.002
1.003
1.004
Datei2
2.001
2.002
2.003
2.004
Datei3
3.001
3.002
3.003
3.004
usw.
Gewünschte Ausgabe:
1.001;2.001;3.001;4.001;5.001;6.001;7.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004
Wie geht das mit einem kurzen Skript in Awk?
Antwort1
Wie steeldriver sagte, ist die sinnvollste Möglichkeit, dies zu tun, Folgendes paste
:
$ paste -d';' file*
1.001;2.001;3.001;4.001;5.001;6.001;7.001;8.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002;8.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003;8.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004;8.004
Wenn Sie jedoch Folgendes verwenden müssen awk
:
$ awk '{a[FNR]=a[FNR](FNR==NR?"":";")$0} END{for (i=1;i<=FNR;i++) print a[i]}' file*
1.001;2.001;3.001;4.001;5.001;6.001;7.001;8.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002;8.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003;8.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004;8.004
Das awk-Skript behält alle Daten im Speicher. Wenn die Dateien groß sind, könnte das ein Problem sein. Für diese Aufgabe paste
ist es aber ohnehin besser und einfacher.
Wie es funktioniert
In diesem Skript a
ist ein Array mit a[i]
die Ausgabe für Zeile i
. Während wir jede der nachfolgenden Dateien durchlesen, hängen wir die neuen Informationen für Zeile i
an das Ende von an a[i]
. Nachdem wir mit dem Lesen der Dateien fertig sind, drucken wir die Werte in aus a
. Genauer gesagt:
a[FNR]=a[FNR](FNR==NR?"":";")$0
FNR
ist die Zeilennummer der aktuellen Datei, die wir lesen, und$0
ist der Inhalt dieser Zeile. Dieser Code wird$0
am Ende von angehängta[FNR]
. Außer wenn wir noch die erste Datei lesen, setzen wir vor ein Semikolon$0
. Dies geschieht mit der komplex aussehenden ternären Anweisung:(FNR==NR?"":";")
. Dies ist eigentlich nur ein if-then-else-Befehl. Wenn wir die erste Datei lesen, das heißt wennFNR==NR
, dann gibt es einen leeren String zurück""
. Wenn nicht, gibt es ein Semikolon zurück,;
.END{for (i=1;i<=FNR;i++) print a[i]}
Nachdem wir mit dem Lesen aller Dateien fertig sind, werden die Daten ausgedruckt, die wir im Array gesammelt haben
a
.
Antwort2
POSIX Awk; das funktioniert mit einer beliebigen Anzahl von Dateien, und die Dateien müssen nicht einmal die gleiche Anzahl von Zeilen haben. Das Skript läuft weiter, bis alle Dateien keine Zeilen mehr haben:
BEGIN {
do {
br = ch = 0
while (++ch < ARGC)
if (getline < ARGV[ch]) {
printf ch < ARGC - 1 ? $0 ";" : $0 RS
br = 1
}
} while (br)
}