he", "she" />

Почему это регулярное выражение приводит к четырем элементам?

python regex split

106 просмотра

3 ответа

2822 Репутация автора

Я хочу , чтобы разбить строку на , ->, =>, или те , обматывают несколькими пробелами, а это означает , что я могу получить два пункта, sheи heиз следующих строк после того , как раскол:
"she he", "she he", "she he ", "she he ", "she->he", "she ->he", "she=>he", "she=> he", " she-> he ", " she => he \n"

Я попытался с помощью этого:

re.compile("(?<!^)((\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split(' she  -> he \n')

Что я получаю список с четырьмя пунктами: [' she', ' -> ', ' -> ', 'he \n'].

И для этого,

re.compile("(?<!^)((\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he')

Я получаю это ['she', ' ', None, 'he'].

Почему там четыре предмета? И как я могу получить только два без двух средних?

Автор: Lerner Zhang Источник Размещён: 09.09.2016 05:53

Ответы (3)


3 плюса

2417 Репутация автора

Решение

Если вы можете просто лишить свою входную строку. Из вашего описания все, что вам нужно, это разделить слова на или \s+или \s*->\s*или\s*=>\s*

Итак, вот мое решение:

p = re.compile(r'\s*[-=]>\s*|\s+')
input1 = "she he"
input2 = " she  -> he \n".strip()

print p.split(input1)
print p.split(input2)

Ваш вывод будет просто «она» и «он»:

['she', 'he']
Автор: sisanared Размещён: 09.09.2016 06:20

1 плюс

106589 Репутация автора

Как уже указывалось в комментариях, каждая пара скобок в вашем регулярном выражении образует группу захвата, и каждое из них возвращается split()функцией регулярного выражения . Согласно документации ,

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

Регулярные выражения Python имеют возможность не захватывать скобки. Вы используете (?:вместо просто (открывающую скобку для группировки без захвата.

>>> re.compile("(?<!^)((\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he')
['she', ' ', None, 'he']
>>> re.compile("(?<!^)(?:(?:\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he')
['she', 'he']

Не совсем понятно, почему вы явно включаете вкладку в класс символов \s; \sуже включает в себя вкладку в качестве одного из многочисленных пробельных символов он соответствует.

Также не ясно, что вы ожидаете, $\nчтобы соответствовать. $это конец строки и \nбуквальный символ новой строки, так что вы, похоже, пытаетесь справиться с новой строкой; но $уже один покрывает это. Единственная разница между $и $\nзаключается в том, что если конец строки (последняя строка многострочной строки) не заканчивается символом новой строки, это не будет соответствовать последнему.

Это (?<!^)также своеобразно - лучший способ избежать совпадения с пустой строкой - убедиться, что ваше регулярное выражение всегда соответствует чему-либо.

Из ваших требований, кажется, что

re.compile(r'\s*[-=]>\s*|\s+').split('he she')

будет делать то, что вы хотите более кратко и читабельно. Это соответствует ASCII-стрелке (с одним или двумя штрихами) с необязательными пробелами с обеих сторон, или, если это не удается, возвращается к последовательности пробелов.

Автор: tripleee Размещён: 09.09.2016 06:59

0 плюса

337 Репутация автора

Каждый раз, когда вы используете скобки "()", вы создаете группу захвата. Группа захвата является частью матча. Совпадение всегда относится к полной строке регулярного выражения. Вот почему вы получаете 4 результата.

Документация гласит: «Если в шаблоне используются захватывающие скобки, то текст всех групп в шаблоне также возвращается как часть полученного списка».

Вы можете попытаться сделать группы "не захватывающими", как предложил Роуинг. Сделайте это, просто добавив "?:" Внутри скобок, которые вы не хотите записывать.

Я бы просто исключил скобки:

res = re.compile("\\s*[-=]>\\s*|\\s*").split(' she  -> he \n')
res = filter(None, res)
res = list(res)

Выход:

['she', 'he']
Автор: Toastgeraet Размещён: 09.09.2016 07:16
Вопросы из категории :
32x32