2016-07-06 36 views
1

Ich möchte den Header einer Textdatei mit einer anderen Textdatei kombinieren. Ich weiß, dass ich es mitGibt es einen einfachen einzeiligen Ansatz, um die Ausgabe eines Unix-Befehls mit einer Datei zu kombinieren?

head -n1 file1.txt > header.txt 
cat header.txt file2.txt > file2_withHeader.txt 

tun kann, aber das erzeugt eine unnötige Zwischendatei und es ist zwei Schritte. Gibt es eine Möglichkeit, einen Schritt zu machen, ohne eine Zwischendatei zu erzeugen?

Ich war dieses

cat $(head -n1 file1.txt) file2.txt > file2_withHeader.txt 

denken, aber es funktioniert nicht, weil $(head -n1 file1.txt) keine Datei ist, damit es nicht verketten kann.

Dank

Antwort

0

Alle drei anderen Antworten auf diese Frage sind gut, und da jeder auf eine andere Art antwortet, wäre es eine gute Übung, jeden zu lernen. LC-datascientist 's und Diego' s Antwort jeder Spawn eine Subshell, so λuser 's Zwei-Zeilen-Ansatz, vielleicht mit && zwischen den beiden Befehlen, ist die idealste.

Wenn Sie wirklich diese in einem Befehl möchten, die nicht eine Unterschale nicht starten, können Sie awk (mawk) verwenden:

awk 'BEGIN { getline < file1.txt; print } 1' file2.txt 

gawk kann es noch eleganter dank der nextfile Befehl tun:

gawk '1; NR == FNR { nextfile }' file1.txt file2.txt 

Diese tun das gleiche: die erste Zeile von file1.txt und druckt sie dann die gesamte file2.txt druckt.

Der mawk Code verwendet getline, um eine einzelne Zeile von einer gegebenen Eingabe in $0 zu lesen (in diesem Fall; siehe die Manpage), wir können das tun, bevor wir file2.txt lesen. 1 ist wahr, daher löst diese zweite Klausel immer aus und löst die Standardaktion aus (print $0).

Der gawk Code druckt zuerst, dann verwendet NR == FNR, um festzustellen, dass Sie bei der ersten Datei (die Gesamtzahl der Datensätze (Zeilen) und die Anzahl der Datensätze der aktuellen Datei ist die gleiche) suchen, in diesem Fall ist es bereits Zeit, um zur zweiten Datei zu wechseln.


Für die ersten drei Zeilen muss mawk eine Schleife:

awk 'BEGIN { for (i=0;i<3;i++) { getline < file1.txt; print } } 1' file2.txt 

und gawk muss lediglich eine weitere Bedingung:

gawk '1; NR == FNR && NR >= 3 { nextfile }' file1.txt file2.txt 
+0

Danke für alle Vorschläge. Es ist in eine wirklich interessante Konversation und Lernerfahrung für mich geraten. Wenn mehr Leute ihre One-Liner oder Ansätze zum Teilen haben, höre ich sie gerne. @Adam Katz, wenn ich mehr als nur die erste Zeile der ersten Datei (mehrere Zeilen) nehmen will, oder sagen, ich möchte Zeilen 2 und 3 aus 'file1.txt' kopieren und sie an den Anfang von' hinzufügen file2.txt' mit 'awk' oder' gawk', wie ändere ich diese awk und gawk Befehle, die du zur Verfügung gestellt hast? –

+0

Ich habe die Antwort mit einer Version aktualisiert, die die ersten drei Zeilen abruft. Ändern Sie einfach die Zahl "3" auf die gewünschte Zahl. 'gawk' kann leicht verändert werden, um genaue Zeilennummern zu spezifizieren (' NR == FNR && (NR == 2 || NR == 4) 'wird zB die Zeilen 2 und 4 der ersten Datei erhalten). –

0

Sie können tatsächlich mit den Umleitungen anhängen:

head -n1 file1.txt > result.txt 
cat file2.txt >> result.txt 
+0

Sie können mit Et-Zeichen dieses "one" line machen (' && ') oder ein Semikolon ('; '):' head -n1 file1.txt> result.txt && cat datei2.txt >> result.txt'. Die Ampersands verhindern das Ausführen des zweiten Befehls, wenn der erste fehlschlägt. –

0

Danke, λuser. Das ist eine Option, die ich auch tun kann.

Eigentlich habe ich gerade den One-Liner herausgefunden, auf den ich gehofft hatte.

(head -n1 file1.txt; cat file2.txt) > file2_withHeader.txt 

Sorry, ich erkannte dies die gleiche Frage wie andere ist zu fragen zwei Befehle in Unix zu kombinieren, so dass diese beantwortet tatsächlich ist.

+1

Sie können auch 'sed 1q file1.txt | verwenden cat - file2.txt> file2_withHeader.txt'. Die Verwendung von 'sed 1q' anstelle von' head -n1' ist kosmetisch; mit 'cat - file2.txt' wird' cat' zum Lesen der Standardeingabe vor dem Lesen von 'file2.txt'. Es gibt zahlreiche andere Möglichkeiten, es auch zu tun. '{sed 1q file1.txt; cat datei2.txt; }> file2_withHeader.txt' ist ein anderer. –

+0

@ LC-datascientist Beachten Sie, dass Ihr '(...)' einen weiteren ganzen Prozess erzeugt, wohingegen Jonathans '{...}' nur eine zusammengesetzte Anweisung ist, die in der aktuellen Shell ausgeführt wird und somit effizienter ist. Beachten Sie auch, dass Sie im '{...}' Fall ein schließendes ';' brauchen. –

0

in bash können Sie auch

cat <(head -n 1 file1.txt) file2.txt > file2_withHeader.txt 

tun, was ich glaube, es war die Sie gesucht haben.