Как разбить строку и сохранить в ней разделители - PullRequest
1 голос
/ 27 апреля 2019

@ edzech спросил, как можно разбить строку и сохранить в ней разделители.Его вопрос был помечен как дубликат , тогда как подход здесь отличается от «дубликата».

Мы хотим разбить строку, но сохраняя в ней разделители, мы не хотим, чтобы они разделялись.Вкратце, для <abc>d<e><f>ghi<j> мы хотим:

['<abc>', 'd', '<e>', '<f>', 'ghi', '<j>']

вместо:

['<', 'abc', '>' 'd', '<', 'e', '>', '<', 'f', '>', 'ghi', '<', 'j', '>']

Использование split не помогает, так как split соответственнов сепаратор.Мы хотим, чтобы оно было привязано к его содержанию.

Ответы [ 3 ]

1 голос
/ 27 апреля 2019

Я полагаю, что вы можете использовать split с этим регулярным выражением

(?<=>)(?=[a-z<])|(?<=[a-z>])(?=<)

https://regex101.com/r/WNy5n9/1

Это не более чем 2 варианта с парными утверждениями взгляд назад / вперед.

Расширенное

   (?<= > )                      # Behind a  >
   (?= [a-z<] )                  # Ahead either a-z or <
|                              # or,
   (?<= [a-z>] )                 # Behind either a-z or >
   (?= < )                       # Ahead a  <

Обновление
Обратите внимание, что в версиях Python до версии 3.7 разбиение
на пустое совпадениене был обработан правильно.
Предположительно, они не могли определить разницу между пустой строкой
и / или как выполнить удар вдоль при совпадениях нулевой ширины.

Похоже, они вытащили свои головы из своих ** теперь в версии 3.7,
, так что вы идете ..

Демо

Версия 3.7.3

>>> import sys
>>> print( sys.version )
3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 21:26:53) [MSC v.1916 32 bit (Intel)]

Код

>>> import re
>>> rx = re.compile( r"(?<=>)(?=[a-z<])|(?<=[a-z>])(?=<)" )
>>> s = "<abc>d<e><f>ghi<j>test><g>"
>>> x =  re.split( rx, s )
>>> print ( x )
['<abc>', 'd', '<e>', '<f>', 'ghi', '<j>', 'test>', '<g>']
1 голос
/ 27 апреля 2019

В предлагаемом решении исключение из результата исключает одно открытие < или закрытие >, которые не являются частью пары <>.

Если вы также хотите сохранить <или > вы можете использовать:

<[^<>]*>|(?:(?!<[^<>]*>).)+

Пояснение

  • <[^<>]*> Открытие матча <, затем 0+ раз не >, затем закрытие >
  • | Или
  • (?:(?!<[^<>]*>).)+ Закаленный жадный жетон, сопоставьте любой символ, если то, что находится справа, не является шаблоном открытия до закрытия

Regex demo | Python demo

Например:

import re
content = "<abc>d<e><f>ghi<j>test><g>"
result = re.findall(r"<[^<>]*>|(?:(?!<[^<>]*>).)+", content)
print(result)

Результат

['<abc>', 'd', '<e>', '<f>', 'ghi', '<j>', 'test>', '<g>']
1 голос
/ 27 апреля 2019

Вот решение.

import re

content = "<abc>d<e><f>ghi<j>"
result = re.findall(r"<.*?>|[^<>]+", content)

print(result)

Выход:

['<abc>', 'd', '<e>', '<f>', 'ghi', '<j>']

Пояснения:

  • регулярное выражение <.*?> означает все, что соответствует <content>
  • регулярное выражение [^<>]+ означает все остальное

Вкратце, findall найдет все, что соответствует <content>, в противном случае, все остальное. Таким образом, содержимое будет разделено без потери разделителей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...