Extrahieren von Textzeilen aus einer langen Datei

Extrahieren von Textzeilen aus einer langen Datei

Ich habe folgende Textdatei:

#unimportant comment
#possible more unimportant comments
#info1 info2 info3 ,importantname1
importanttext1
#info1 info2 info3 ,importantname2
importanttext2
#info1 info2 info3 ,importantname3
importanttext3

Ich möchte jede Datei in einzelne Dateien aufteilen. Ich muss lediglich die nicht kommentierten URLs extrahieren, das Beibehalten von Kommentaren ist optional. Ich möchte, dass jede Datei einen Namen wie importantname1.txt oder den Namen nach dem Komma am Ende jeder Kommentarzeile erhält, angehängt mit .txt.

also hätte importantname1.txt folgenden Inhalt:

importanttext1 

oder möglicherweise

#info1 info2 info3 ,importantname1
importanttext1

Die Zeile würde also extrahiert und mit dem Dateinamen nach dem Kommentar gespeichert und mit .txt angehängt, in diesem Fall Dateiname importantname1.txt

Ich muss dies für jeden Zeilensatz in der Beispieldatei tun. Das Beibehalten der Kommentare ist unwichtig, aber ich brauche es, damit es skriptfähig ist. Ich muss auch eine unbekannte Anzahl von Kommentarzeilen im Header berücksichtigen. Die Kommentarzeile wird immer vor jeder importanttextX-Zeile stehen.

Antwort1

Versuchen:

awk -F, '/^#/{f=$NF".txt";cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file

Beispiel

Auf Ihre Beispieleingabe angewendet:

$ awk -F, '/^#/{f=$NF".txt";cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file

Nachdem das obige ausgeführt wurde, befinden sich die folgenden Dateien im Verzeichnis:

$ ls
file  importantname1.txt  importantname2.txt  importantname3.txt

Der Inhalt der neuen Dateien ist:

$ cat importantname1.txt 
#info1 info2 info3 ,importantname1
importanttext1
$ cat importantname2.txt 
#info1 info2 info3 ,importantname2
importanttext2
$ cat importantname3.txt 
#info1 info2 info3 ,importantname3
importanttext3

Wie es funktioniert

Awk liest die Eingabedatei Zeile für Zeile durch. Unser Skript klassifiziert diese Zeilen als Kommentare oder Nicht-Kommentare. Bei Kommentarzeilen werden Dateiname und Kommentar gespeichert. Bei Nicht-Kommentaren wird eine neue Datei erstellt und ausgedruckt.

  • `-F,

    Dies weist awk an, bei der Eingabe ein Komma als Feldtrennzeichen zu verwenden. Auf diese Weise ist der Dateiname immer das letzte Feld.

  • /^#/{f=$NF".txt";cmt=$0; next}

    Wenn eine Zeile mit beginnt #, speichern wir das letzte Feld, $NF, plus .txtals Dateinamen f. Die gesamte Kommentarzeile wird als gespeichert cmt. Anschließend weisen wir awk an, den Rest der Befehle zu überspringen und direkt von vorne in der nextZeile zu beginnen.

  • printf "%s\n%s\n",cmt,$0 >f; close(f)

    Bei Zeilen ohne Kommentar drucken wir den zuletzt gesehenen Kommentar, cmt, und die aktuelle Zeile, $0, in den zuletzt gesehenen Dateinamen f. Anschließend schließen wir den Datei-Handle für f.

Schutz vor fehlerhaften Dateinamen

Wenn die Felder, die als Dateinamen verwendet werden sollen, enthalten /, interpretiert das Betriebssystem die Dateinamen so, als ob sie Verzeichnisse enthalten. Um das zu vermeiden, können wir all /durch -using gsub(/\//, "-", f)wie folgt ersetzen:

awk -F, '/^#/{f=$NF".txt";gsub(/\//, "-", f); cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file

Antwort2

Eine Kombination aus grepund csplitkönnte die Aufgabe erledigen, indem a) grepalle nicht auskommentierten Zeilen sowie die vorangehende Infozeile angepingt werden und b) die Ausgabe basierend auf der Infokommentarzeile aufgeteilt wird:

grep -v -B1 '^#' file | csplit -z - '/^#/' '{*}'

D. h., extrahieren Sie keine -vZeilen, die am Anfang ein # haben, ^#sondern eine Zeile davor -B1. Teilen Sie dann den eingehenden Pipe-Input -bei jedem # am Zeilenanfang auf, ignorieren Sie leere Dateien -zund wiederholen Sie dies so oft wie möglich {*}.

Das Umbenennen müsste ein separater Schritt sein ( csplitbenennt die Ausgabe automatisch als xx00, xx01 ... - ändert Prä- und Suffix jeweils mit den Optionen -fund -b).

#/bin/bash
for f in xx* ; do
   mv "$f" "$( sed -n '2p' "$f" )".txt
done

verwandte Informationen