Verwendung Awk eine Datei zu verarbeiten, wobei jeder Datensatz verschiedene Felder mit fester Breite hat
-
21-09-2019 - |
Frage
Ich habe einige Datendateien aus einem Altsystem, dass ich mag mit Awk verarbeiten. Jede Datei besteht aus einer Liste von Datensätzen. Es gibt mehrere verschiedene Datensatztypen und jeden Datensatztyp hat einen anderen Satz von Feldern mit fester Breite (es gibt keine Feldtrennzeichen). Die ersten beiden Zeichen des Datensatzes zeigen die Art, von dem aus Sie dann wissen, welche Felder folgen sollte. Eine Datei könnte wie folgt aussehen:
AAField1Field2LongerField3
BBField4Field5Field6VeryVeryLongField7Field8
CCField99
Mit Gawk ich einstellen kann der FIELDWIDTHS , aber das gilt für die gesamte Datei (es sei denn, ich auf einem Rekord-by-Rekord bin fehlt eine Möglichkeit, dies zu Einstellung Basis), oder ich kann zu einem Zeitpunkt FS auf „“ und Prozess die Datei ein Zeichen gesetzt, aber das ist ein bisschen beschwerlich.
Gibt es eine gute Möglichkeit, die Felder aus einer solchen Datei mit Awk?
zu extrahierenBearbeiten : Ja, ich könnte verwenden Perl (oder etwas anderes). Ich bin gespannt, noch zu wissen, ob es eine vernünftige Art und Weise ist es aber mit Awk zu tun.
Lösung
Hoffentlich werden Sie in die richtige Richtung führen. Angenommen, Ihre Aufzeichnungen mit mehreren Leitungen sind garantiert durch einen ‚CC‘ Typ Zeile beendet werden können Vorprozess Textdatei if-then Logik einfach. Ich habe angenommen, Sie benötigen fields1,5 und 7 auf einer Zeile und einer Probe awk Skript wäre.
BEGIN {
field1=""
field5=""
field7=""
}
{
record_type = substr($0,1,2)
if (record_type == "AA")
{
field1=substr($0,3,6)
}
else if (record_type == "BB")
{
field5=substr($0,9,6)
field7=substr($0,21,18)
}
else if (record_type == "CC")
{
print field1"|"field5"|"field7
}
}
Eine awk Skriptdatei namens program.awk und Pop diesen Code hinein. Führen Sie das Skript mit:
awk -f program.awk < my_multi_line_file.txt
Andere Tipps
Sie können vielleicht zwei Pässe verwenden:
1step.awk
/^AA/{printf "2 6 6 12" }
/^BB/{printf "2 6 6 6 18 6"}
/^CC/{printf "2 8" }
{printf "\n%s\n", $0}
2step.awk
NR%2 == 1 {FIELDWIDTHS=$0}
NR%2 == 0 {print $2}
Und dann
awk -f 1step.awk sample | awk -f 2step.awk
Sie haben wahrscheinlich zu unterdrücken müssen (oder zumindest ignorieren) awk
des integrierten Feldtrenncode, und verwenden Sie ein Programm entlang der Linien von:
awk '/^AA/ { manually process record AA out of $0 }
/^BB/ { manually process record BB out of $0 }
/^CC/ { manually process record CC out of $0 }' file ...
Die manuelle Bearbeitung wird etwas schwierig sein kann - ich nehme an, Sie müssen die substr
Funktion verwenden, um jedes Feld von Position zu extrahieren, so was ich habe als eine Zeile pro Satzart mehr wie eine Zeile pro Feld sein wird, in jedem Datensatz-Typ sowie die Folge auf Druck.
Ich glaube, besser könnte aus seinem mit Perl und seiner unpack
Funktion, aber awk
kann es zu handhaben, wenn auch verbosely.
Könnten Sie Perl verwenden und dann eine auspacken Vorlage auswählen, basierend auf den ersten beiden Zeichen der Zeile?
Bessere einige voll funktionsSkriptSprache wie Perl oder Ruby verwenden.
Was ist 2-Skripte? Z.B. 1. Skript Einsätze Feldtrenn basierend auf den ersten Zeichen, dann die zweite sollte es verarbeiten?
oder in erster Linie eine Funktion in Ihrem AWK Skript zu definieren, die die Linien in Variablen teilt auf der Grundlage der Eingabe -. Ich würde diesen Weg gehen, für die mögliche Wiederverwendung