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 n
und 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 , sed
um 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 join
Befehlstaste on. Der letzte sed
Befehl setzt die Ziffern wieder an ihren Platz und entfernt die zuvor hinzugefügten zusätzlichen Leerzeichen.
Ein vim
Guru 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.}