Ich habe mehr als 1000 Zeilen in einer Datei. Die Datei beginnt wie folgt (Zeilennummern hinzugefügt):
Station Name
Station Code
A N DEV NAGAR
ACND
ABHAIPUR
AHA
ABOHAR
ABS
ABU ROAD
ABR
Ich muss dies in eine Datei mit durch Kommas getrennten Einträgen konvertieren, indem ich alle zwei Zeilen verbinde. Die endgültigen Daten sollten so aussehen
Station Name,Station Code
A N DEV NAGAR,ACND
ABHAIPUR,AHA
ABOHAR,ABS
ABU ROAD,ABR
...
Ich habe versucht, ein Shell-Skript und dann ein echo
Komma dazwischen zu schreiben . Aber ich denke, ein einfacher, effektiver Einzeiler würde die Arbeit hier vielleicht in sed
/ erledigen awk
.
Irgendwelche Ideen?
Antworten:
Einfach benutzen
cat
(wenn du Katzen magst ;-)) undpaste
:Erläuterung:
paste
Liest aus einer Reihe von Dateien und fügt die entsprechenden Zeilen zusammen (Zeile 1 aus der ersten Datei mit Zeile 1 aus der zweiten Datei usw.):Anstelle eines Dateinamens können wir
-
(Bindestrich) verwenden.paste
Nimmt die erste Zeile von file1 (das ist stdin). Dann möchte es die erste Zeile aus Datei2 lesen (die auch stdin ist). Da jedoch die erste stdin-Zeile bereits gelesen und verarbeitet wurde, wartet nun auf den Eingabestream die zweite stdin-Zeile, diepaste
glücklich mit der ersten zusammenklebt. Die-d
Option setzt das Trennzeichen als Komma und nicht als Tabulator.Alternativ dazu tun
PS Ja, man kann das oben genannte vereinfachen
oder
Das hat den Vorteil, nicht zu verwenden
cat
.Ich habe dieses Idiom jedoch aus Gründen der Klarheit nicht absichtlich verwendet - es ist weniger ausführlich und ich mag es
cat
(CATS ARE NICE). Also bitte nicht bearbeiten.Wenn Sie das Einfügen Katzen vorziehen (Einfügen ist der Befehl, um Dateien horizontal zu verketten, während Katze sie vertikal verkettet), können Sie Folgendes verwenden:
quelle
paste
Befehl funktioniert einwandfrei. Können Sie das bitte etwas näher erläutern? Die Bindestriche ???cat
Argument. Gehtsed "N;s/\n/,/" file.in > file.out
nichtWenn jemand hier landet und alle Linien zu einem CSV-Einzeiler zusammenfassen möchte, versuchen Sie es
quelle
Verbinden Sie (N) mit sed alle 2 Zeilen und ersetzen Sie die neue Zeile (\ n) durch ",".
quelle
Beachten Sie auch, dass wir die Eingabedatei direkt bearbeiten können, da wir lediglich ein Zeichen durch ein anderes ersetzen (jede zweite Zeile durch ein Komma):
(Beachten Sie jedoch, dass dies auf Nicht-Unix-Systemen mit CRLF-Terminatoren (wie Microsoft-Systemen) nicht funktioniert, die von einigen emulierten POSIX-Systemen
paste
möglicherweise nicht unter Unix behandelt werden.)quelle
1
hier in tut1<>
? ist das ein Tippfehler?Hier ist ein Einzeiler (obwohl möglicherweise Millionen von Befehlsausführern), der reines Bash verwendet:
Ich verwende eine Unterschale (die Klammer), damit ich nicht speichern und wiederherstellen muss
IFS
. Was man sonst tun sollte, um die Benutzerumgebung nicht durcheinander zu bringen, falls die Quelle stammt. Die Alternative wäre, dass neue IFS passieren nur ,read
wie inIFS= read -r name
,IFS= read -r code
.Die Tatsache, dass alle Befehle in der Schleife in der Shell integriert sind, macht die Leistung akzeptabel und ist sogar schneller als die anderen Lösungen für kleine Dateien. Aber viele Leute würden es für eine schlechte Praxis halten, und man sollte vorsichtig sein, wenn man es auf etwas anderes verallgemeinert.
quelle
while IFS='\n' read -r name; do IFS='\n' read -r code ... done < file.in
, eine Redewendung, die ich oft in Shell-Skripten sehe. Das-r
Flagread
bedeutet "interpretiere das Zeichen '\' gefolgt von dem Zeichen 'n' im Standard-Stream als zwei Zeichen und nicht als Zeilenvorschub". Wahrscheinlich ist es ästhetischer, die Unterschale so zu erstellen, wie Sie es tun, als sie zu wiederholenIFS='\n'
.-r
die Lösung technisch verbessert. Groß! Ich bin kein Fan von der Idee, eine VeränderungIFS
zweimal zu bestehen. Wenn ich eins gelesen hätte, super schön, aber nicht zweimal. Das ist natürlich Ansichtssache . Die Verwendung einer Subshell geht ein bisschen über das allgemeine Bash-Wissen hinaus, das ich sagen würde, sodass viele Leute Probleme haben werden, den Zweck dieser Subshell zu verstehen. Das ist eine schlechte Sache.Für den vollständigen Satz von Antworten kann eine mögliche
awk
Lösung sein:quelle
printf
? Schlägt in seltenen Fällen fehl, wenn ein Sendername einen Formatbezeichner enthält. (Siehe pastebin.com/wgxFttrJ für ein Beispiel.) Aber das ist nur eine Vermutung, die von Downvote mir nicht.Hoary alte Kastanie einer
awk
Redewendungquelle
awk '{ORS=NR%2?",":"\n"};1'
ist kürzer und idiomprint
die Absicht klar ist.1
ist für alteawk
print
sed
eine Weile gekämpft, bevor ich gesucht habe, aberawk
das Kombinieren aller 4 Zeilen wurde einfacher. Sparte mir einen Ausflug ins$EDITOR
!Auch mit Perl möglich,
perl -pe 's/^\d+\.\s+//;$.&1?chomp:print","' file
quelle
Beispielsweise:
Ausgabe: (Anmerkung:
xargs -L number_of_columns
funktioniert gut mit fast jeder Anzahl von Spalten, nicht nur alle zwei Zeilen)quelle
POSIX-Lösung mit
pr
:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pr.html
quelle