#python-3.x #regex
#python-3.x #регулярное выражение
Вопрос:
строка A
foo bar bar foo bar foo
строка B
foo bar bar foo
В строке A двойной пробел встречается многократно.
Я хочу сопоставлять только такие строки, как строка B, в которой только один раз встречается двойной пробел.
Я пытался
^.*s{2}.*$
но это будет соответствовать обоим.
Как я могу получить желаемый результат? Спасибо.
Комментарии:
1. Зачем вообще использовать regex для этого? Не кажется лучшим вариантом. Просто найдите количество вхождений двух последовательных пробелов в строке. Или, если вы хотите предотвратить подсчет более двух пробелов, вы могли бы использовать регулярное выражение и подсчитать количество
(?<![ ]{2})[ ]{2}(?![ ]{2})
совпадений.2. @41686d6564 у меня был поток строковых данных с этим шаблоном, строка с только одним появлением двойного пробела означает, что это двойной столбец, но с более чем однократным появлением двойного пробела не классифицируется. итак, мне нужно различать эти два случая.
3. Используйте шаблон в моем предыдущем комментарии. Он будет сопоставлять все два последовательных символа пробела, которым непосредственно не предшествуют другие символы пробела (т. Е. ровно два). Теперь подсчитайте количество совпадений в каждой строке, и вы получите свое решение (т. Е. вы ожидаете только одно совпадение, не больше и не меньше). Удачи!
4. @41686d6564, есть много вопросов, опубликованных с тегом regex, где могут быть решения без регулярных выражений, которые, возможно, в некотором смысле лучше. Некоторые из этих вопросов просто отражают желание задающего улучшить свое понимание некоторых функций регулярных выражений, без утверждения, что использование регулярного выражения было бы предпочтительным подходом к данной проблеме. Любыми способами предлагайте решения без регулярных выражений для вопросов, имеющих теги регулярных выражений (за исключением случаев, когда в вопросе указано, что необходимо использовать регулярное выражение), но признайте, что у задающего могут быть веские причины для желания решения в регулярных выражениях.
Ответ №1:
Если вы хотите сопоставить строки, которые содержат не более одной строки из двух или более пробелов между словами, вы могли бы использовать следующее регулярное выражение.
r'^(?!(?:.*(?<! ) {2,}(?! )){2})'
Обратите внимание, что это выражение соответствует
abc de fgh
где между 'c'
и 'd'
четыре пробела.
Механизм регулярных выражений Python выполняет следующие операции.
^
(?! : begin negative lookahead
(?: : begin non-capture group
.* : match 0 characters other than line terminators
(?<! : begin negative lookbehind
[ ]{2,} : match 2 spaces
(?! ) : negative lookahead asserts match is not followed by a space
) : end negative lookbehind
) : end non-capture group
{2} : execute non-capture group twice
) : end negative lookahead
Ответ №2:
Вы можете сделать:
^(?!.*[ t]{2,}.*[ t]{2,})
# Negative look ahead assertion that states 'only start the match
# on this line IF there are NOT 2 (or potentially more) breaks with
# two (or potentially more) of tabs or spaces'.
Если вы хотите использовать ОДИН двойной пробел в строке, но не более:
^(?=.*[ t]{2,})(?!.*[ t]{2,}.*[ t]{2,})
# Positive look ahead that states 'only start this match if there is
# at least one break with two tabs or spaces'
# BUT
# Negative look ahead assertion that states 'only start the match
# on this line IF there are NOT 2 (or potentially more) breaks with
# two (or potentially more) of tabs or spaces'.
Если вы хотите ограничить только двумя пробелами (не табуляциями и не более чем 2 пробелами):
^(?=.*[ ]{2})(?!.*[ ]{2}.*[ ]{2})
# Same as above but remove the tabs as part of the assertion
Примечание: В вашем регулярном выражении у вас есть s
в качестве класса для пробела. Это также соответствует [rntfv ]
, поэтому как горизонтальные, так и вертикальные символы пробела.
Примечание 2: Вы можете сделать это и без регулярного выражения (предполагая, что вам нужны только строки, в которых есть 1 и только 1 двойной пробел):
txt='''
line A
foo bar bar foo bar foo
line B
foo bar bar foo'''
>>> [line for line in txt.splitlines() if len(line.split(' '))==2]
['foo bar bar foo']
Комментарии:
1. спасибо, это работает. не могли бы вы, пожалуйста, объяснить, зачем ему нужно дополнительное
[ ]{2}
в конце? я не могу понять логику здесь..
Ответ №3:
Вы можете получить совпадение без поиска, начав сопоставление с 1 символов без пробелов.
Затем необязательно повторите одиночный символ пробела, за которым следуют символы без пробела до и после сопоставления символа с двойным пробелом.
Класс отрицаемых символов [^Srn]
будет сопоставлять любые символы пробела, за исключением новой строки или возврата каретки. Если вы также хотите разрешить сопоставление новых строк, вы могли бы использовать s
^S (?:[^Srn]S )*[^Srn]{2}(?:S [^Srn])*S $
Объяснение
^
Начало строкиS
Сопоставьте 1 символы без пробелов(?:
Группа без захвата[^Srn]S
Сопоставьте символ пробела без перевода строки
)*
Закройте группу и повторите 0 раз[^Srn]{2}
Сопоставьте 2 пробельных символа без перевода строки(?:
Группа без захватаS [^Srn]
Сопоставьте 1 символы без пробелов, за которыми следует символ пробела без перевода строки
)*
Закройте группу a и повторите 1 разS
Сопоставьте 1 символы без пробелов$
Конец строки