it-swarm.com.de

Wie füge ich alle zwei Zeilen von der Kommandozeile aus zu einer zusammen?

Ich habe eine Textdatei mit dem folgenden Format. Die erste Zeile ist der "KEY" und die zweite Zeile ist der "VALUE".

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 wäre besser, wenn ich ein Trennzeichen wie $ Oder , Verwenden könnte:

KEY 4048:1736 string , 3

Wie füge ich zwei Zeilen zu einer zusammen?

129
shantanuo

awk:

awk 'NR%2{printf "%s ",$0;next;}1' yourFile

beachten Sie, dass am Ende der Ausgabe eine leere Zeile steht.

sed:

sed 'N;s/\n/ /' yourFile
159
Kent

paste ist gut für diesen Job:

paste -d " "  - - < filename
212
glenn jackman

Alternative zu sed, awk, grep:

xargs -n2 -d'\n'

Dies ist am besten, wenn Sie N Zeilen verbinden möchten und nur eine durch Leerzeichen begrenzte Ausgabe benötigen.

Meine ursprüngliche Antwort war xargs -n2 das eher nach Wörtern als nach Zeilen trennt. -d kann verwendet werden, um die Eingabe durch ein einzelnes Zeichen zu teilen.

29
nnog

Es gibt mehr Möglichkeiten, einen Hund zu töten als zu hängen. [1]

awk '{key=$0; getline; print key ", " $0;}'

Fügen Sie das gewünschte Trennzeichen in die Anführungszeichen ein.


Verweise:

  1. Ursprünglich "Viele Möglichkeiten, die Katze zu häuten", wurde auf einen älteren, möglicherweise ursprünglicheren Ausdruck zurückgegriffen, der auch nichts mit Haustieren zu tun hat.
25
ghoti

Hier ist ein anderer Weg mit awk:

awk 'ORS=NR%2?FS:RS' file
$ cat file
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
$ awk 'ORS=NR%2?FS:RS' file
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

Wie von Ed Morton in den Kommentaren angegeben, ist es aus Sicherheitsgründen besser, geschweifte Klammern und aus Gründen der Portabilität parens hinzuzufügen.

awk '{ ORS = (NR%2 ? FS : RS) } 1' file

ORS steht für Output Record Separator. Wir testen hier eine Bedingung mit dem NR, in dem die Zeilennummer gespeichert ist. Wenn das Modulo von NR ein wahrer Wert (> 0) ist, setzen wir das Ausgabefeldtrennzeichen auf den Wert von FS (Feldtrennzeichen), der standardmäßig ein Leerzeichen ist, ansonsten weisen wir den Wert zu von RS (Record Separator) das ist newline.

Wenn Sie hinzufügen möchten , als Trennzeichen verwenden Sie dann:

awk '{ ORS = (NR%2 ? "," : RS) } 1' file
11
jaypal singh

Obwohl es den Anschein hat, als würden die vorherigen Lösungen funktionieren, würde die Ausgabe in Stücke gehen, wenn im Dokument eine einzige Anomalie auftritt. Unten ist ein bisschen sicherer.

sed -n '/KEY/{
N
s/\n/ /p
}' somefile.txt
11
J.D.

Hier ist meine Lösung in Bash:

while read line1; do read line2; echo "$line1, $line2"; done < data.txt
10
Hai Vu

"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.

 ex -c "%g/KEY/j" -c "wq" data.txt

Dies besagt, dass für jede Zeile, wenn sie mit "KEY" übereinstimmt, ein j in der folgenden Zeile ausgeführt wird. Nachdem dieser Befehl abgeschlossen ist (gegen alle Zeilen), setzen Sie ein w rite und q uit ab.

7
Justin

Sie können awk wie folgt verwenden, um je 2 Zeilenpaare zu kombinieren:

awk '{ if (NR%2 != 0) line=$0; else {printf("%s %s\n", line, $0); line="";} } \
     END {if (length(line)) print line;}' flle
4
anubhava

Wenn Perl eine Option ist, können Sie Folgendes versuchen:

Perl -0pe 's/(.*)\n(.*)\n/$1 $2\n/g' file.txt
4
andrefs

Eine kleine Variation von Glenn Jackmans Antwort using paste: wenn der Wert für das -d Trennzeichenoption enthält mehr als ein Zeichen, paste durchläuft die Zeichen nacheinander und kombiniert mit dem -s options macht das weiter, während dieselbe Eingabedatei verarbeitet wird.

Dies bedeutet, dass wir verwenden können, was immer wir wollen, als Trennzeichen plus der Escape-Sequenz \n, um zwei Zeilen gleichzeitig zusammenzuführen.

Komma verwenden:

$ paste -s -d ',\n' infile
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

und das Dollarzeichen:

$ paste -s -d '$\n' infile
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

Was dieses nicht kann , ist die Verwendung eines aus mehreren Zeichen bestehenden Trennzeichens.

Wenn paste POSIX-kompatibel ist, wird die neue Zeile der letzten Zeile in der Datei nicht geändert. Dies gilt auch für eine Eingabedatei mit einer ungeraden Anzahl von Zeilen

KEY 4048:1736 string
3
KEY 0:1772 string

paste greift das Trennzeichen in der letzten Zeile nicht an:

$ paste -s -d ',\n' infile
KEY 4048:1736 string,3
KEY 0:1772 string
3
Benjamin W.

Sie können auch den folgenden vi-Befehl verwenden:

:%g/.*/j
3
Jdamian

Eine andere Lösung mit vim (nur als Referenz).

Lösung 1:

Öffne die Datei in vim vim filename Und führe dann den Befehl :% normal Jj Aus

Dieser Befehl ist leicht zu verstehen:

  • %: für alle Zeilen
  • normal: normalen Befehl ausführen
  • Jj: Führe den Join-Befehl aus und springe dann zur untersten Zeile

Speichern Sie danach die Datei und beenden Sie 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 sie mit :wq.

2
Jensen
nawk '$0 ~ /string$/ {printf "%s ",$0; getline; printf "%s\n", $0}' filename

Das liest sich so

$0 ~ /string$/  ## matches any lines that end with the Word string
printf          ## so print the first line without newline
getline         ## get the next line
printf "%s\n"   ## print the whole line and carriage return
1
Shahab Khan

In dem Fall, in dem ich zwei Zeilen kombinieren musste (um die Verarbeitung zu vereinfachen), aber die Daten über die spezifischen hinaus zulassen musste, fand ich dies nützlich

data.txt

string1=x
string2=y
string3
string4
cat data.txt | nawk '$0 ~ /string1=/ { printf "%s ", $0; getline; printf "%s\n", $0; getline } { print }' > converted_data.txt

die Ausgabe sieht dann so aus:

converter_data.txt

string1=x string2=y
string3
string4
1
Ben Taylor

Der einfachste Weg ist hier:

  1. Entfernen Sie gerade Linien und schreiben Sie sie in eine temporäre Datei 1.
  2. Entfernen Sie ungerade Zeilen und schreiben Sie sie in eine temporäre Datei 2.
  3. Kombinieren Sie zwei Dateien in einer, indem Sie den Befehl Einfügen mit -d verwenden (bedeutet Leerzeichen löschen).
sed '0~2d' file > 1 && sed '1~2d' file > 2 && paste -d " " 1 2
0
Serg
Perl -0pE 's{^KEY.*?\K\s+(\d+)$}{ $1}msg;' data.txt > data_merged-lines.txt

-0 verschlingt die ganze Datei, anstatt sie zeilenweise zu lesen;
pE umschließt den Code mit einer Schleife und druckt die Ausgabe, siehe Details in http://perldoc.Perl.org/perlrun.html ;
^KEY Entspricht "KEY" am Zeilenanfang, gefolgt von einer nicht gierigen Übereinstimmung von irgendetwas (.*?) vor der Sequenz von

  1. ein oder mehrere Leerzeichen \s+ jeglicher Art einschließlich Zeilenumbrüchen;
  2. eine oder mehrere Ziffern (\d+) die wir erfassen und später wieder einfügen als $1;

gefolgt vom Zeilenende $.

\K schließt praktisch alles auf der linken Seite von der Substitution aus, also { $1} ersetzt nur 1-2 Sequenzen, siehe http://perldoc.Perl.org/perlre.html .

0
Onlyjob

Eine allgemeinere Lösung (es kann mehr als eine Folgezeile verbunden werden) als Shell-Skript. Dies fügt eine Linie zwischen jedem hinzu, da ich Sichtbarkeit brauchte, aber das kann leicht behoben werden. In diesem Beispiel endete die Zeile "key" mit: und keine anderen Zeilen.

#!/bin/bash
#
# join "The rest of the story" when the first line of each   story
# matches $PATTERN
# Nice for looking for specific changes in bart output
#

PATTERN='*:';
LINEOUT=""
while read line; do
    case $line in
        $PATTERN)
                echo ""
                echo $LINEOUT
                LINEOUT="$line"
                        ;;
        "")
                LINEOUT=""
                echo ""
                ;;

        *)      LINEOUT="$LINEOUT $line"
                ;;
    esac        
done
0
Jan Parcel