Ich habe eine Textdatei mit dem folgenden Format. Die erste Zeile ist der "SCHLÜSSEL" und die zweite Zeile ist der "WERT".
KEY 4048:1736 string
3
KEY 0:1772 string
1
KEY 4192:1349 string
1
KEY 7329:2407 string
2
KEY 0:1774 string
1
Ich brauche den Wert in der gleichen Zeile wie der Schlüssel. Die Ausgabe sollte also so aussehen ...
KEY 4048:1736 string 3
KEY 0:1772 string 1
KEY 4192:1349 string 1
KEY 7329:2407 string 2
KEY 0:1774 string 1
Es ist besser, wenn ich ein Trennzeichen wie $
oder verwenden könnte ,
.
KEY 4048:1736 string , 3
Wie füge ich zwei Zeilen zu einer zusammen?
pr
,paste
,awk
,xargs
,sed
undpure bash
! (xargs
ist langsamer, langsamer als Bash !)Antworten:
awk:
Beachten Sie, dass am Ende der Ausgabe eine leere Zeile steht.
sed:
quelle
printf
Erweiterungszeichenfolgen wie darin enthalten%s
sind$0
. Dieser Fehler kann folgendermaßen vermieden werden:'NR%2{printf "%s ",$0;next;}1'
1
nach dem Schließen der Klammer, weil es wirklich schwer zu googeln ist ?paste
ist gut für diesen Job:quelle
paste
auf der anderen Seite verhält sich perfekt. +1.cut
, vergesse aber immerpaste
. Es rockt für dieses Problem. Ich musste alle Zeilen von stdin kombinieren und tat es einfach mitpaste -sd ' ' -
.-
gemein stdin, sopaste - -
gemein lesen von stdin, dann lesen von stdin, du kannst so viele davon stapeln, wie du willst, wie ich erwarte.Alternative zu sed, awk, grep:
Dies ist am besten geeignet, wenn Sie N Zeilen verbinden möchten und nur eine durch Leerzeichen getrennte Ausgabe benötigen.
Meine ursprüngliche Antwort war,
xargs -n2
dass sich Wörter und nicht Zeilen trennen.-d
kann verwendet werden, um die Eingabe durch ein einzelnes Zeichen zu teilen.quelle
-d '\n'
xargs
Benutzer, wusste das aber nicht. Toller Tipp.Es gibt mehr Möglichkeiten, einen Hund zu töten als zu hängen. [1]
Fügen Sie in die Anführungszeichen ein beliebiges Trennzeichen ein.
Verweise:
quelle
$0
. Dergetline
Befehl erfasst auch "die nächste" Eingabezeile und platziert sie$0
. Die erste Anweisung erfasst also die erste Zeile, und der Befehl print verkettet das, was in der Variablen gespeichert wurde,key
mit einer Zeichenfolge, die ein Komma enthält, zusammen mit der Zeile, die mit abgerufen wurdegetline
. Klarer? :)Hier ist meine Lösung in Bash:
quelle
Obwohl es den Anschein hat, dass die vorherigen Lösungen funktionieren würden, würde die Ausgabe in Stücke gehen, wenn eine einzelne Anomalie im Dokument auftritt. Unten ist ein bisschen sicherer.
quelle
/KEY/
das Was macht derp
am Ende?/KEY/
Suche nach der Zeile mit demKEY
. dasp
druckt das Ergebnis aus. Es ist sicherer, weil es die Operation nur auf Zeilen mit einemKEY
darin anwendet .Hier ist ein anderer Weg mit
awk
:Wie von Ed Morton in den Kommentaren angegeben, ist es besser, aus Sicherheitsgründen Zahnspangen und aus Gründen der Tragbarkeit Parens hinzuzufügen.
ORS
steht für Output Record Separator. Was wir hier tun, ist das Testen einer Bedingung unter Verwendung der, inNR
der die Zeilennummer gespeichert ist. Wenn das Modulo vonNR
ein wahrer Wert ist (> 0), setzen wir den Ausgabe-Feldtrenner auf den Wert vonFS
(Feldtrenner), der standardmäßig Leerzeichen ist, andernfalls weisen wir den Wert vonRS
(Datensatztrenner) zu, der eine neue Zeile ist.Wenn Sie
,
als Trennzeichen hinzufügen möchten, verwenden Sie Folgendes:quelle
ORS
und wird so behandelt, alstrue
ob ORS einen Wert erhält, der nicht Null oder eine Nullzeichenfolge ist, und richtig errät, dass es ein Stich statt eines numerischen Vergleichs sein sollte? Ist es etwas anderes? Ich bin mir wirklich nicht sicher und hätte es so geschriebenawk '{ORS=(NR%2?FS:RS)}1' file
. Ich habe den ternären Ausdruck in Klammern gesetzt, um auch die Portabilität sicherzustellen."ex" ist ein skriptfähiger Zeileneditor, der zur selben Familie gehört wie sed, awk, grep usw. Ich denke, es könnte das sein, wonach Sie suchen. Viele moderne vi-Klone / Nachfolger haben auch einen vi-Modus.
Dies sagt für jede Zeile, wenn es passt „KEY“ eine ausführen j oin der folgenden Zeile. Nachdem dieser Befehl beendet ist (gegen alle Linien), geben eine w rite und q uit.
quelle
Wenn Perl eine Option ist, können Sie versuchen:
quelle
-0
Perl, das Datensatztrennzeichen$/)
auf Null zu setzen, damit wir mehrere Zeilen in unserem übereinstimmenden Muster überspannen können. Die Manpages sind etwas zu technisch, als dass ich herausfinden könnte, was dies in der Praxis bedeutet.Sie können awk wie folgt verwenden, um immer zwei Zeilenpaare zu kombinieren:
quelle
Eine andere Lösung mit vim (nur als Referenz).
Lösung 1 :
Öffnen Sie die Datei in vim
vim filename
und führen Sie den Befehl aus:% normal Jj
Dieser Befehl ist sehr einfach zu verstehen:
Speichern Sie danach die Datei und beenden Sie mit
:wq
Lösung 2 :
Führen Sie den Befehl in der Shell aus,
vim -c ":% normal Jj" filename
speichern Sie die Datei und beenden Sie mit:wq
.quelle
norm!
robuster alsnormal
im FallJ
neu zugeordnet wurde. +1 für vim Lösung.Sie können auch den folgenden Befehl vi verwenden:
quelle
:%g//j
da Sie nur eine Übereinstimmung für den auszuführenden Join benötigen und eine Nullzeichenfolge immer noch eine gültige Regex ist.//
stattdessen das vorherige Suchmuster verwendet. Wenn es kein vorheriges Muster gibt, meldet Vim einfach einen Fehler und unternimmt nichts. Die Lösung von Jdamian funktioniert ständig.Eine geringfügige Abweichung von der Antwort von Glenn Jackman mit
paste
: Wenn der Wert für die-d
Trennzeichenoption mehr als ein Zeichen enthält,paste
werden die Zeichen einzeln durchlaufen und in Kombination mit den-s
Optionen weiterhin ausgeführt, während dieselbe Eingabedatei verarbeitet wird.Dies bedeutet, dass wir alles, was wir wollen, als Trennzeichen und die Escape-Sequenz verwenden können
\n
, um zwei Zeilen gleichzeitig zusammenzuführen.Komma verwenden:
und das Dollarzeichen:
Dies kann nicht verwendet werden, indem ein Trennzeichen verwendet wird, das aus mehreren Zeichen besteht.
Als Bonus
paste
ändert dies nicht die neue Zeile der letzten Zeile in der Datei , wenn POSIX-kompatibel ist, also für eine Eingabedatei mit einer ungeraden Anzahl von Zeilen wiepaste
wird das Trennungszeichen in der letzten Zeile nicht anheften:quelle
Dies lautet wie folgt
quelle
Für den Fall, dass ich zwei Zeilen kombinieren musste (um die Verarbeitung zu vereinfachen), aber die Daten über das Spezifische hinaus zulassen, fand ich dies nützlich
data.txt
Die Ausgabe sieht dann so aus:
convert_data.txt
quelle
Ein anderer Ansatz mit vim wäre:
Dies gilt a
join
(für die Zeile darunter) für alle Zeilen, in denen das Wort enthaltenKEY
ist. Ergebnis:quelle
Der einfachste Weg ist hier:
quelle
-0
verschlingt die gesamte Datei, anstatt sie Zeile für Zeile zu lesen;pE
Umschließt den Code mit einer Schleife und druckt die Ausgabe. Weitere Informationen finden Sie unter http://perldoc.perl.org/perlrun.html .^KEY
Übereinstimmung mit "KEY" am Zeilenanfang, gefolgt von einer nicht gierigen Übereinstimmung von irgendetwas (.*?
) vor der Sequenz von\s+
jeglicher Art, einschließlich Zeilenumbrüche;(\d+)
die wir erfassen und später wieder einfügen als$1
;gefolgt vom Zeilenende
$
.\K
Schließt bequem alles auf der linken Seite von der Substitution aus und{ $1}
ersetzt nur 1-2 Sequenzen, siehe http://perldoc.perl.org/perlre.html .quelle
Eine allgemeinere Lösung (ermöglicht das Zusammenfügen mehrerer Follow-up-Zeilen) als Shell-Skript. Dies fügt eine Linie zwischen jedem hinzu, weil ich Sichtbarkeit brauchte, aber das ist leicht zu beheben. In diesem Beispiel endete die Zeile "Schlüssel" mit: und keine anderen Zeilen.
quelle
Versuchen Sie die folgende Zeile:
Setzen Sie das Trennzeichen dazwischen
zB wenn das Trennzeichen ist
|
, dann:quelle
Sie können
xargs
wie folgt verwenden:quelle
xargs -n 2
aber diese Antwort erklärt dies überhaupt nicht.