Я знаю, что название довольно запутанно, но эту проблему трудно сформулировать просто. Надеюсь, у этого есть решение, и это результат того, что я новичок в мире регулярных выражений.
Я пытаюсь разобрать текст из книги по химии и преобразовать его в JSON, но у меня возникают проблемы с разделением текста по его основному идентификатору. Все это делается в среде Python 3.10.
Рассмотрим следующую строку:
0047 Heptasilver nitrate octaoxide
[12258-22-9] Ag NO
7 11
(Ag O ) .AgNO
3 4 2 3
Alone, or Sulfides, or Nonmetals
The crystalline product produced by electrolytic oxidation
of silver nitrate (and possibly as formulated) detonates
feebly at 110°C. Mixtures with phosphorus and sulfur
explode on impact, hydrogen sulfide ignites on contact,
and antimony trisulfide ignites when ground with the salt.
Mellor, 1941, Vol. 3, 483–485
See other SILVER COMPOUNDS
See related METAL NITRATES
0048 Aluminium
[7429-90-5] Al
Al
HCS 1980, 135 (powder)
Finely divided aluminium powder or dust forms highly
explosive dispersions in air [1], and all aspects of pre-
vention of aluminium dust explosions are covered in 2
US National Fire Codes [2]. The effects on the ignition
properties of impurities introduced by recycled metal used
to prepare dust were studied [3]. Pyrophoricity is elimi-
nated by surface coating aluminium powder with poly-
styrene [4]. Explosion hazards involved in arc and flame
spraying of the powder were analyzed and discussed [5],
and the effect of surface oxide layers on flammability
was studied [6]. The causes of a severe explosion in
1983 in a plant producing fine aluminium powder were
analyzed, and improvements in safety practices discussed
[7]. A number of fires and explosions involving aluminiumdust arising from grinding, polishing, and buffing opera-
tions were discussed, and precautions detailed [8] [12]
[13]. Atomized and flake aluminium powders attain
See other METALS
See other REDUCANTS
0049 Aluminium-cobalt alloy (Raney cobalt alloy)
[37271-59-3] 50:50; [12043-56-0] Al Co; Al—Co
5
[73730-53-7] Al Co
2
Al Co
The finely powdered Raney cobalt alloy is a significant
dust explosion hazard.
See DUST EXPLOSION INCIDENTS (reference 22)
0050 Aluminium–copper–zinc alloy
(Devarda’s alloy)
[8049-11-4] Al—Cu—Zn
Al Cu Zn
Silver nitrate: Ammonia, etc.
See DEVARDA’S ALLOY
See other ALLOYS0051 Aluminium amalgam (Aluminium–
mercury alloy)
[12003-69-9] (1:1) Al—Hg
Al Hg
The amalgamated aluminium wool remaining from prepa-
ration of triphenylaluminium will rapidly oxidize and
become hot upon exposure to air. Careful disposal is nec-
essary [1]. Amalgamated aluminium foil may be pyro-
phoric and should be kept moist and used immediately [2].
1. Neely, T. A. et al., Org. Synth., 1965, 45, 109
2. Calder, A. et al., Org. Synth., 1975, 52, 78
See other ALLOYS
Эта строка содержит информацию о 5 различных соединениях, которые идентифицируются 4-значным номером в начале, за которым следует название, а затем в другой строке уникальный идентификатор CAS в квадратных скобках.
Я пытаюсь разделить это на отдельные подстроки для каждого объекта, идентифицируя 4-значное число, за которым всегда следуют другие идентификаторы, и разделяя текст в этой точке.
В настоящее время я использую это регулярное выражение, которое правильно определяет 4-значные идентификаторы:
\n(\d{4})\s(?:[\s\S]*?)(?:\[\d*?-\d*?-\d*?\]|\[ *?\] [a-zA-Z]*?)
Однако это также включает в себя несколько экземпляров других 4-значных чисел, которые не являются идентификаторами, например даты в основном тексте, такие как дата «1983» в тексте составной записи алюминия (0048).
Я пытался использовать отрицательный просмотр вперед с тем же выражением, которое я использую для выделения 4-значного идентификатора, но ни один из способов, которые я пробовал, не работал. И теперь я не уверен, возможно ли это вообще, или, возможно, я слишком усложняю это.
Другой способ сделать это — использовать CAS (в квадратных скобках), но это будет хуже, так как есть записи с несколькими или даже пустыми CAS.
Любой совет будет принят с благодарностью!
Возможно вот так ^See.*\n(\d{4})\s(?:[\s\S]*?)(?:\[\d+-\d+-\d+])regex101.com/r/MHk5qr/1 или вот так \n(\d{4}).*(?:\n\(.*)*\n\[\d+-\d+-\d+]regex101.com/r/czf39b/1
@Thefourthbird Правило состоит в том, что за ним сразу следует имя (текст с буквами, цифрами и символами), разрыв строки и последовательность чисел, заключенных в квадратные скобки.
Звучит как ^(\d{4}).*\n\[\d+-\d+-\d+]regex101.com/r/64EMh7/1
@Thefourthbird Последнее выражение, кажется, отлично работает для разделения дат и намного проще, чем то, что я экспериментировал до сих пор. Единственное, чего ему не хватает, так это учета пустых квадратных скобок, но это достаточно легко исправить. Большое спасибо!






Несколько замечаний по вашему шаблону:
[a-zA-Z]*? в конце шаблона, так как это последняя часть и не жадная, поэтому она не будет соответствовать никаким символам.\d*?-\d*?-\d*? и \[ *?\], не должны быть не жадными, поскольку указанный повторяемый символ не может пересекать следующий символЕсли совпадение всегда должно начинаться с новой строки:
\n(\d{4}).*(?:\n\(.*)*\n\[(?: *|\d+-\d+-\d+)]
Объяснение
\n Совпадение с новой строкой(\d{4}) Запишите 4 цифры в группа 1.* Сопоставьте остальную часть строки(?:\n\(.*)* При желании повторите сопоставление новой строки и (, за которой следует остальная часть строки\n Совпадение с новой строкой\[(?: *|\d+-\d+-\d+)] Совпадение [...], где могут быть только пробелы или цифры с дефисом между нимиСм. демонстрация регулярных выражений.
Если квадратные скобки должны быть прямо на следующей строке:
^(\d{4}).*\n\[(?: *|\d+-\d+-\d+)]
См. другой демонстрация регулярных выражений.
Еще раз большое спасибо. Но еще один вопрос, если не возражаете. Что делать, если текст, следующий за 4-значным идентификатором, занимает несколько строк?
@RicardoBessa Можете ли вы создать здесь пример регулярного выражения101 с частью, которую вы хотите сопоставить, и поделиться ссылкой здесь?
Я нашел хороший пример проблемы, здесь regex101.com/r/RfgDCO/1
@RicardoBessa И вы хотите сопоставить все строки после этого? До следующего появления 4 цифр или конца строки? Примерно так regex101.com/r/aHnjTm/1
@RicardoBessa Или как regex101.com/r/9jbl8h/1
Нет, в этом случае я хочу только сопоставить текст между 4-значным идентификатором и первыми квадратными скобками. Пример, который я разместил с идентификаторами 0071 и 0072, показывает мою проблему, когда я пытаюсь сопоставить многострочные имена, он также может поймать нежелательный текст, если есть дата
@RicardoBessa попробуй regex101.com/r/cwq98i/1
О да, кажется, это прекрасно работает. Это довольно сложно, поэтому мне потребуется немного времени, чтобы полностью понять логику, стоящую за ним. Большое спасибо, что показали мне, как это сделать!
Каково правило, чтобы 4 цифры не были годом? Должна ли строка с 4 цифрами всегда сопровождаться строкой, начинающейся с
[или(? Или 4 цифры всегда должны начинаться с нуля? Или ему должен предшествоватьSeeв строке перед?