Wie verbinde ich mehrere Zeilen basierend auf einem Muster?

Wie verbinde ich mehrere Zeilen basierend auf einem Muster?

Ich möchte mehrere Zeilen in einer Datei basierend auf einem Muster verbinden, das beide Zeilen gemeinsam haben.

Dies ist mein Beispiel:

{101}{}{Apples}
{102}{}{Eggs}
{103}{}{Beans}
{104}...
...

{1101}{}{This is a fruit.}
{1102}{}{These things are oval.}
{1103}{}{You have to roast them.}
{1104}...
...

Ich möchte mich den Linien anschließen {101}{}{Apples}und{1101}{}{This is a fruit.}

{101}{}{Apples}{1101}{}{This is a fruit.}zur weiteren Verarbeitung in eine Zeile zusammenfassen .

Gleiches gilt für die anderen Zeilen.

Wie Sie sehen, haben beide Zeilen die gleiche Nummer wie 101, aber ich habe keine Ahnung, wie ich das hinbekomme. Irgendwelche Ideen?

/BEARBEITEN:

Ich habe einen "Workaround" gefunden:

Löschen Sie zunächst im VISUAL BLOCK-Modus alle vorangehenden Zeichen „{1“ aus Gruppe zwei mit C-V(oder einer ähnlichen Tastenkombination), sortieren Sie dann alle Zeilen nach Nummer mit :%sort nund verbinden Sie anschließend jede zweite Zeile mit :let @q = "Jj"gefolgt von 500@q.

Das funktioniert, aber ich habe nur noch {101}{}{Apples} 101}{}{This is a fruit.}. Ich müsste dann in jeder Zeile die fehlenden Zeichen "{1" hinzufügen, was nicht ganz das ist, was ich will. Jede Hilfe ist willkommen.

Antwort1

Anstatt das zu löschen {1, machen Sie einfach

:%sort rn /\d\d\d}/

Dadurch wird eine numerische Sortierung durchgeführt, in jeder Zeile werden jedoch nur drei Ziffern gefolgt von einem } berücksichtigt.

Auch um die Linien nachher zu verbinden, würde ich tun

:g/{\d\d\d}/j!

Antwort2

So können Sie dies in der Shell mit einer Datei tun:

join -j 2 \
    <(sed -n '/^{...}/{s/{/{ /;s/}/ }/;p}' inputfile) \
    <(sed -n '/^{....}/{s/{./& /;s/}/ }/;p}' inputfile) |
    sed 's/^\([^ ]*\) { }{}\({[^}]*}\) {1 }\({.*}\)$/{\1}{}\2{1\1}\3/'

Es verwendet die ersten beiden Aufrufe von , sedum die Datei basierend auf der Anzahl der Ziffern zwischen den ersten geschweiften Klammern aufzuteilen und fügt Leerzeichen um die letzten drei Ziffern hinzu ( {101}wird zu { 101 }und {1101}wird zu {1 101 }). Dann verwendet es diese dreistelligen Zahlen als Feld für die joinBefehlstaste on. Der letzte sedBefehl setzt die Ziffern wieder an ihren Platz und entfernt die zuvor hinzugefügten zusätzlichen Leerzeichen.

Ein vimGuru könnte darin wahrscheinlich etwas Besseres machen vim. Ich könnte mit AWK etwas Einfacheres als das oben genannte machen.

Antwort3

Hier ist ein Beispiel für die Verwendung des Vim/Ex-Editors von der Befehlszeile aus für ein Muster:

$ ex +'redir @a|sil g/101}/' +'redi>>/dev/stdout|echon join(split(@a),"")' -scq! input.txt 
{101}{}{Apples}{1101}{}{This is a fruit.}

Bei mehreren Mustern wiederholen Sie entweder mit zusätzlichen Befehlen, fügen eine Schleife hinzu oder führen Sie eine Schleife aus der Shell aus, z. B.

$ for i in `seq 1 3`; do ex +"redir @a|sil g/10$i}/" +'redi>>/dev/stdout|echo join(split(@a),"")' -scq! input.txt; done
{101}{}{Apples}{1101}{}{Thisisafruit.}
{102}{}{Eggs}{1102}{}{Thesethingsareoval.}
{103}{}{Beans}{1103}{}{Youhavetoroastthem.}

Wenn Sie zum Parsen der Daten nur die Shell verwenden, ist es viel einfacher, z. B.:

$ grep "101}" input.txt | xargs
{101}{}{Apples} {1101}{}{This is a fruit.}

Für mehrere Zeilen:

$ for i in `seq 1 4`; do grep "10$i}" input.txt | xargs; done
{101}{}{Apples} {1101}{}{This is a fruit.}
{102}{}{Eggs} {1102}{}{These things are oval.}
{103}{}{Beans} {1103}{}{You have to roast them.}

verwandte Informationen