Регулярное выражение для IF C с присвоенным массивом - PullRequest
2 голосов
/ 27 февраля 2020

IF C - это разновидность файлов STEP, используемых для строительных проектов. IF C содержит информацию о строящемся здании. Файл основан на тексте, и его легко читать. Я пытаюсь разобрать эту информацию в python словарь. Общий формат каждой строки будет подобен следующему

2334 = IFCMATERIALLAYERSETUSAGE (# 2333, .AXIS2.,. POSITIVE., - 180.);

в идеале это должно быть проанализировано в int # 2334, IFCMATERIALLAYERSETUSAGE, # 2333, .AXIS2.,. POSITIVE., - 180. Я нашел решение Regex включает два совпадения в первом совпадении https://regex101.com/r/RHIu0r/10 для части проблемы. Однако в некоторых случаях данные содержат массивы вместо значений, как в примере ниже

2335 = IFCRELASSOCIATESMATERIAL ('2ON6 $ yXXD1GAAH8whbdZm c', # 5, $, $, (# 40, # 221, # 268, # 281), # 2334);

Этот случай необходимо проанализировать как # 2335, IFCRELASSOCIATESMATERIAL, '2ON6 $ yXXD1GAAH8whbdZm c', # 5, $, $, [# 40, # 221, # 268, # 281], # 2334 Где [# 40, # 221, # 268, # 281] - это хранимое в одной переменной значение в виде массива. Массив может находиться в средней или последней переменной.

Сможете ли вы помочь в создании регулярного выражения для получения желаемых результатов, которые я создал https://regex101.com/r/mqrGka/1 со случаями для проверки

1 Ответ

2 голосов
/ 28 февраля 2020

Вот решение, которое продолжается с точки, которую вы достигли с помощью регулярного выражения в тестовых случаях:

file = """\
#1=IFCOWNERHISTORY(#89024,#44585,$,.NOCHANGE.,$,$,$,1190720890);
#2=IFCSPACE(';;);',#1,$);some text);
#2=IFCSPACE(';;);',#1,$);
#2885=IFCRELAGGREGATES('1gtpBVmrDD_xsEb7NuFKc8',#5,$,$,#2813,(#2840,#2846,#2852,#2858,#2879));
#2334=IFCMATERIALLAYERSETUSAGE(#2333,.AXIS2.,.POSITIVE.,-180.);
#2335=IFCRELASSOCIATESMATERIAL('2ON6$yXXD1GAAH8whbdZmc',#5,$,$,(#40,#221,#268,#281),#2334);
""".splitlines()

import re
d = dict()
for line in file:
    m = re.match(r"^#(\d+)\s*=\s*([a-zA-Z0-9]+)\s*\(((?:'[^']*'|[^;'])+)\);", line, re.I|re.M)
    attr = m.group(3)       # attribute list string
    values = [m.group(2)]   # first value is the entity type name
    while attr:
        start = 1
        if attr[0] == "'": start += attr.find("'", 1)   # don't split at comma within string
        if attr[0] == "(": start += attr.find(")", 1)   # don't split item within parentheses
        end = attr.find(",", start)                     # search for a comma / end of item
        if end < 0: end = len(attr)
        value = attr[1:end-1].split(",") if attr[0] == "(" else attr[:end]
        if value[0] == "'": value = value[1:-1]         # remove quotes
        values.append(value)
        attr = attr[end+1:]                             # remove current attribute item
    d[m.group(1)] = values                              # store into dictionary
...