Python Split Regex не разделяет то, что мне нужно

у меня это в файле

import re

sample = """Name: @s
Owner: @a[tag=Admin]"""

target = r"@[sae](\[[\w{}=, ]*\])?"
regex = re.split(target, sample)

print(regex)

Я хочу разделить все слова, начинающиеся с @, вот так:
["Name: ", "@s", "\nOwner: ", "@a[tag=Admin]"]

Но вместо этого выдает это:
['Name: ', None, '\nOwner: ', '[tag=Admin]', '']

Как его отделить?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
65
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Я бы использовал re.findall здесь:

sample = """Name: @s
Owner: @a[tag=Admin]"""
parts = re.findall(r'@\w+(?:\[.*?\])?|\s*\S+\s*', sample)
print(parts)  # ['Name: ', '@s', '\nOwner: ', '@a[tag=Admin]']

Используемый здесь шаблон регулярного выражения говорит, что он соответствует:

@\w+          a tag @some_tag
(?:\[.*?\])?  followed by an optional [...] term
|             OR
\s*\S+\s*     any other non whitespace term,
              including optional whitespace on both sides

Если я правильно понимаю требования, вы можете сделать это следующим образом:

import re
s = """Name: @s
Owner: @a[tag=Admin]
"""
rgx = r'(?=@.*)|(?=\r?\n[^@\r\n]*)'
re.split(rgx, s)
  #=> ['Name: ', '@s', '\nOwner: ', '@a[tag=Admin]\n']

Демо

Регулярное выражение можно разбить следующим образом.

(?=         # begin a positive lookahead
  @.*       # match '@' followed by >= 0 chars other than line terminators
)           # end positive lookahead
|           # or
(?=         # begin a positive lookahead
  \r?\n     # match a line terminator
  [^@\r\n]* # match >= 0 characters other than '@' and line terminators 
)           # end positive lookahead

Обратите внимание, что совпадения имеют нулевую ширину.

Помогу получить футболку +1.

Tim Biegeleisen 21.03.2022 14:06

@ Тим, я точно так же помог тебе с этим кольцом для гольфа 0,5 м.

Cary Swoveland 21.03.2022 15:26

re.split ожидает, что регулярное выражение будет соответствовать разделителям в строке. Он возвращает только те части разделителей, которые равны захвачен. В случае вашего регулярного выражения это только часть между скобками, если они есть.

Если вы хотите, чтобы в списке отображался весь разделитель, заключите все регулярное выражение в круглые скобки:

target = r"(@[sae](\[[\w{}=, ]*\])?)"

Но вам, вероятно, лучше не захватывать внутреннюю группу. Вы можете изменить его на группу без захвата, используя (?:…) вместо (…):

target = r"(@[sae](?:\[[\w{}=, ]*\])?)"

В вашем выводе вы сохраняете [tag=Admin], поскольку эта часть находится в группе захвата, а использование разделения также может возвращать пустые строки.

Другой вариант — указать разрешенный формат данных и вместо разделения захватывать части на 2 группы.

(\s*\w+:\s*)(@[sae](?:\[[\w{}=, ]*])?)

Шаблон соответствует:

  • ( Снять группа 1
    • \s*\w+:\s* Сопоставьте 1+ словесных символов и : между необязательными пробелами
  • ) Закрыть группу
  • ( Захватить группа 2
    • @[sae] Совпадение @, за которым следует либо sae
    • (?:\[[\w{}=, ]*])? По желанию совпадать [...]
  • ) Закрыть группу

Пример кода:

import re

sample = """Name: @s
Owner: @a[tag=Admin]"""
target = r"(\s*\w+:\s*)(@[sae](?:\[[\w{}=, ]*])?)"

listOfTuples = re.findall(target, sample)
lst = [s for tpl in listOfTuples for s in tpl]
print(lst) 

Выход

['Name: ', '@s', '\nOwner: ', '@a[tag=Admin]']

См. демонстрация регулярных выражений и демонстрация Python.

Другие вопросы по теме