Hallo zusammen,
ich bin auf der Suche, nach einem "schönen" Weg eine .fil-Datei aus Abaqus mittels python in ein array-Format zu bekommen. Anschließend soll eine Auswertung dieser Daten über die Record Keys stattfinden.
Das Format ist sehr gewöhnungsbedürftig und ich konnte mit Hilfe eines replace-Befehls immerhin das Dokument zeilenweise soritieren.
Auf den Buchstaben I folgt ein INTEGER. Der Buchstabe A leitet einen STRING mit 8 Zeichen ein und auf ein D folgt ein FLOAT-Zahl in wissenschaftlicher Schreibweise, nur ist der Exponent durch ein "D" angegebenen, anstatt üblicherweise einem "E".
[codebox=python file=x]'I 19I 41921A6.10-1 A08-Nov-2A015 A09:54:03I 16I 13D 1.000000000000000D+00\nI 16I 41900I 11ADASHPOT2I 12I 11\nI 16I 41900I 12ASPRING2 I 12I 11\nI 12I 42001 \nI 223I 42000D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00I 295I 11I 222I 11D 0.000000000000000D+00D 1.506949602122016D+00D 0.000000000000000D+00AFORCED OASCILLATIAON WITH AVISCOELAASTIC DAMAPING A A A A \nI 14I 41911I 11ANALL \nI 15I 3111I 11D 0.000000000000000D+00D 0.000000000000000D+00\nI 19I 3111I 12D 6.625918346244238D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.478679518984229D+01D 0.000000000000000D+00D 0.000000000000000D+00\nI 19I 3111I 13D 7.480262652497893D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.622259472865796D+01D 0.000000000000000D+00D 0.000000000000000D+00\nI 12I 42001 \n'[/code]
Zum Code, ich hoffe, dass er nicht durch das kopieren umformatiert wurde.
Ein .split() mit den oben verwendeten Buchstaben ist leider nicht ohne weiteres möglich, da in den STRINGS eben diese Buchstaben auch vorkommen, des weiteren erschwert die Exponential-Schreibweise mittels "D" das teilen der FLOATs.
Hat jemand eine Idee?
Grüße,
Stoli
.fil Abaqus-Datei in Array
@Stoli: Ich würde mir dafür einen Parser schreiben. Entweder mit regulären Ausdrücken und ein bisschen Code oder mit Hilfe des `pyparsing`-Moduls.
@Stoli: das läßt sich durch einen einfachen regulären Ausdruck lösen:
Code: Alles auswählen
import re
test = 'I 19I 41921A6.10-1 A08-Nov-2A015 A09:54:03I 16I 13D 1.000000000000000D+00\nI 16I 41900I 11ADASHPOT2I 12I 11\nI 16I 41900I 12ASPRING2 I 12I 11\nI 12I 42001 \nI 223I 42000D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00I 295I 11I 222I 11D 0.000000000000000D+00D 1.506949602122016D+00D 0.000000000000000D+00AFORCED OASCILLATIAON WITH AVISCOELAASTIC DAMAPING A A A A \nI 14I 41911I 11ANALL \nI 15I 3111I 11D 0.000000000000000D+00D 0.000000000000000D+00\nI 19I 3111I 12D 6.625918346244238D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.478679518984229D+01D 0.000000000000000D+00D 0.000000000000000D+00\nI 19I 3111I 13D 7.480262652497893D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.622259472865796D+01D 0.000000000000000D+00D 0.000000000000000D+00\nI 12I 42001 \n'
for i_val, a_val, d_val, unknown in re.findall('I(\s*[+-]?[0-9]+\s*)|A(.{8})|D(\s*[+-]?[0-9.]+(?:D[+-]*[0-9]+)?\s*)|(.)', test):
if i_val: print "I", int(i_val)
if a_val: print "A", a_val
if d_val: print "D", float(d_val.replace('D','e'))
if unkown: raise ValueError(unknown)
`re.Scanner` ist zwar nicht dokumentiert, existiert aber schon seit Ewigkeiten:
Code: Alles auswählen
import re
from pprint import pprint
DATA = (
'I 19I 41921A6.10-1 A08-Nov-2A015 A09:54:03I 16I 13D 1.000000000000000D+00\n'
'I 16I 41900I 11ADASHPOT2I 12I 11\n'
'I 16I 41900I 12ASPRING2 I 12I 11\n'
'I 12I 42001 \n'
'I 223I 42000D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00I 295I 11I 222I 11D 0.000000000000000D+00D 1.506949602122016D+00D 0.000000000000000D+00AFORCED OASCILLATIAON WITH AVISCOELAASTIC DAMAPING A A A A \n'
'I 14I 41911I 11ANALL \n'
'I 15I 3111I 11D 0.000000000000000D+00D 0.000000000000000D+00\n'
'I 19I 3111I 12D 6.625918346244238D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.478679518984229D+01D 0.000000000000000D+00D 0.000000000000000D+00\n'
'I 19I 3111I 13D 7.480262652497893D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.622259472865796D+01D 0.000000000000000D+00D 0.000000000000000D+00\n'
'I 12I 42001 \n'
)
SCANNER = re.Scanner(
[
(r'I[- ]\d+', lambda _, s: int(s[1:])),
(r'A.{8}', lambda _, s: s[1:]),
(
r'D[- ]\d+\.\d+D[+-]\d{2}',
lambda _, s: float(s[1:].replace('D', 'e'))
),
]
)
def scan(line):
result, unparsed = SCANNER.scan(line)
if unparsed.strip():
raise ValueError('unexpeced trailing stuff: {0!r}'.format(unparsed))
return result
def main():
pprint(map(scan, DATA.splitlines()))
if __name__ == '__main__':
main()
Genau das habe ich gesucht - hervorragend, danke!Sirius3 hat geschrieben:@Stoli: das läßt sich durch einen einfachen regulären Ausdruck lösen:
Habe noch ein bisschen was geändert, das "unknown" funktioniert hier auf meinem Rechner nicht, werd es auf einer aktuellen python-Version noch testen.
Das tmp.fil sieht folgendermaßen aus:
tmp.fil
Code: Alles auswählen
*I 19I 41921A6.10-1 A08-Nov-2A015 A09:54:03I 16I 13D 1.000000000000000D+00*
I 16I 41900I 11ADASHPOT2I 12I 11*I 16I 41900I 12ASPRING2 I 12I 11*I 15I 41900I 1
3AMASS I 12*I 16I 41900I 211ADASHPOT2I 13I 12*I 16I 41900I 212ASPRING2 I 13I
12*I 15I 41900I 213AMASS I 13*I 16I 41901I 11D 1.000000000000000D+01D 0.00000
0000000000D+00D 0.000000000000000D+00*I 16I 41901I 12D 1.500000000000000D+01D 0.
000000000000000D+00D 0.000000000000000D+00*I 16I 41901I 13D 2.000000000000000D+0
1D 0.000000000000000D+00D 0.000000000000000D+00*I 15I 41933AD I 11I 211*I
15I 41933AM I 13I 213*I 15I 41933AS I 12I 212*I 16I 41931AFILE I
11I 12I 13*I 16I 41931ANALL I 11I 12I 13*I 15I 41940I 11AANTIALIAASING *I
16I 41940I 12AWarnNodeABCInactiAveDof *I 232I 41902I 11I 12I 13I 10I 10I 10I 1
0I 10I 10I 10I 10I 10I 10I 10I 10I 14I 15I 16I 10I 10I 10I 10I 10I 10I 10I 10I 1
0I 10I 10I 10*I 212I 41922ASTEADY SATATE VIBARATION OAF 2-DOF ASYSTEM (AVISCOELA
ASTIC DAMAPING) A A *I 12I 42001
Code: Alles auswählen
import re
with open('tmp.fil','r') as file_input_r:
with open('output.txt','w') as file_output_w:
contents = file_input_r.read()
newcontents = contents.replace('\n','').replace('*I', '\nI')
for i_val, a_val, d_val, unknown in re.findall('I(\s*[+-]?[0-9]+\s*)|A(.{8})|D(\s*[+-]?[0-9.]+(?:D[+-]*[0-9]+)?\s*)|(.)', newcontents):
if i_val: file_output_w.write(i_val+'\t')
if a_val: file_output_w.write(a_val.replace(' ', '')+'\t')
if d_val: file_output_w.write(d_val.replace('D','e')+'\t')
Danke nochmal !