Antworten:
Schneller Weg (beinhaltet das zweimalige Lesen der Datei):
$ tail -n+2 file | paste -d';' file -
A;B
B;C
C;
paste
kurz darauf gelesen, tail
sodass er sich im Cache befindet. Die Chancen stehen gut, dass es effizienter ist als sed
/ awk
basierte Lösungen. Ein Nachteil ist, dass es nicht an Rohren funktionieren kann.
paste -d';' file <(sed 1d file)
$ sed 'x;G;s_\n_;_;1d;${p;x;s_$_;_;}' file
A;B
B;C
C;
Was dieser sed
Ausdruck tut:
x
: Speichern Sie die eingehende Zeile im Haltebereich und rufen Sie die vorherige abG
: Hänge die neue Zeile (aus dem Haltebereich) an die alte ans_\n_;_
: Zeilenumbruch durch a ersetzen ;
.1d
: Wenn dies die erste Zeile ist, löschen Sie sie (drucken Sie sie nicht aus) und fahren Sie mit der nächsten fort${...;}
: wenn dies die letzte Zeile ist ...p
: Drucken Sie zuerst das verbundene Paarx
: die letzte Zeile abrufens_$_;_
: final anhängen ;
Etwas einfachere sed
Lösung ohne Speicherplatz:
sed '$!N;y/\n/;/;p;y/;/\n/;D' file
$!N
um der nächsten Zeile beizutreten (falls vorhanden; $!
wird bei GNU nicht benötigt, sed
wenn nicht im POSIX-Modus)y/\n/;/
Ersetzen Sie die Newline durch ;
p
Drucken Sie die resultierende Liniey/;/\n/
zurück zu newline wechseln, also mitD
Sie können die erste Zeile entfernen und mit der nächsten fortfahrenC
nicht C;
im Beispiel des OP.
$!y/;/\n/
wenn das Trailing ;
erforderlich ist.
Gleiche Grundidee wie die von Torin gegebene awk-Lösung :
$ perl -lne 'print "$last;$_" if defined $last; $last=$_;END{print "$last;" if $.}' file
A;B
B;C
C;
Oder wenn Sie sich für die ganze Kürze interessieren:
$ perl -lne'$.>1?print"$l;$_":1;$l=$_}{print"$l;"if$.' file
A;B
B;C
C;
Eine Vim-Lösung
Man kann diesen Befehl ausgeben (Dank an Conspicuous Compiler, der dies vorgeschlagen hat):
vim "+%s/\n\(.\+\)*/;\1\n\1" sample.txt
Alternativ und wahrscheinlich üblicher starten Sie Vim, öffnen Sie die Datei und geben Sie den Befehl ex ein:
:%s/\n\(.\+\)*/;\1\n\1
Erläuterung:
Ersetzen Sie das Muster:
\n
\(.+\)
, die die gesamte nächste Zeile zusammensetzt. Der folgende Quantifizierer *
zeigt nur an, dass es null oder mehr Übereinstimmungen geben kannmit den folgenden:
\1
\n
\1
.Nach:
vim '+*ThisReallylongCommand*'
$ perl -lp -0777e 's/\n(?=(.*\n?))/;$1/g' input.txt
;
Zeichen?