Ich habe eine Protokolldatei, die analysiert und analysiert werden muss. Die Datei enthält etwas Ähnliches wie unten:
Datei:
20141101 server contain dump
20141101 server contain nothing
{uekdmsam ikdas
jwdjamc ksadkek} ssfjddkc * kdlsdl
sddsfd jfkdfk
20141101 server contain dump
Basierend auf dem obigen Szenario muss ich überprüfen, ob die Startzeile kein Datum oder keine Nummer enthält, die ich an die vorherige Zeile anhängen muss.
Ausgabedatei:
20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdl sddsfd jfkdfk
20141101 server contain dump
text-processing
sed
awk
William R.
quelle
quelle
-0
wenn für NUL-getrennte Datensätze. Verwenden Sie-0777
diese Option, um die gesamte Datei im Speicher zu schlürfen (was Sie hier nicht benötigen).Kann ein bisschen einfach sein mit
sed
Der erste Teil
:1;N;$!b1
sammelt alle Zeilen in der Datei geteilt durch eine\n
lange ZeileDer zweite Teil streift das Zeilenumbruchsymbol, wenn er auf ein nichtstelliges Symbol mit möglichen Zwischenräumen folgt.
Um Speicherbeschränkungen zu vermeiden (insbesondere bei großen Dateien), können Sie Folgendes verwenden:
Oder vergessen Sie schwierige
sed
Skripte und denken Sie daran, dass das Jahr beginnt2
quelle
tr '\n' $'\a' | sed $'s/\a\a*\( *[^0-9]\)/\1/g' | tr $'\a' '\n'
selbst.+
ist\{1,\}
.[\n]
ist auch nicht tragbar.\n\{1,\}
wäre POSIX.: 1;x
ist das1;x
Label in POSIX seds zu definieren . Sie brauchen also :sed -e :1 -e 'N;$!b1' -e 's/\n\{1,\}\( *[^0-9]\)/\1/g'
. Beachten Sie auch, dass vielesed
Implementierungen eine kleine Begrenzung der Größe ihres Musterbereichs haben (POSIX garantiert nur 10 x LINE_MAX IIRC).Ein Weg wäre:
Dadurch wird jedoch auch die letzte neue Zeile entfernt. Um es erneut hinzuzufügen, verwenden Sie:
Erläuterung
Das
-l
entfernt nachfolgende Zeilenumbrüche (und fügt jedemprint
Anruf einen hinzu, weshalb ichprintf
stattdessen verwende. Wenn die aktuelle Zeile mit Nummern (/^\d+/
) beginnt und die aktuelle Zeilennummer größer als eins ist ($.>1
dies ist erforderlich, um das Hinzufügen zusätzlicher Zeilen zu vermeiden) leere Zeile am Anfang), fügen Sie\n
am Anfang der Zeile ein hinzu. Dasprintf
druckt jede Zeile.Alternativ können Sie alle
\n
Zeichen in\0
ändern und dann diejenigen\0
, die direkt vor einer Zahlenfolge stehen, in\n
erneut ändern :Verwenden Sie stattdessen Folgendes, damit nur Zeichenfolgen mit 8 Zahlen übereinstimmen:
quelle
printf
ist das Format . Verwenden Sieprintf "%s", $_
%10000000000s
zum Beispiel.perl
,echo %.10000000000f | perl -ne printf
bringt meine Maschine in die Knie.Versuchen Sie dies mit awk :
Um es zu benutzen:
quelle
Ein anderer einfachster Weg (als meine andere Antwort) mit dem Algorithmus von awk und terdon :
quelle
END{print ""}
. Alternative:awk -v ORS= 'NR>1 && /^[0-9]{8}/{print "\n"};1;END{print "\n"}'
quelle
Le program en bash:
in einzeiliger Form:
Lösung mit Backslashes, die (
read -r
) und führende Leerzeichen (kurzIFS=
danachwhile
) erhalten:einzeiliges Formular:
quelle
n
. Außerdem werden Leerzeichen entfernt. Aber Sie könnenmksh
dies tun:while IFS= read -r L; do [[ $L = [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]* ]] && print; print -nr -- "$L"; done; print
das wird funktionieren
quelle