Регулярное выражение: начало совпадения или пробел - PullRequest
43 голосов
/ 08 февраля 2009

Может ли регулярное выражение соответствовать пробелу или началу строки?

Я пытаюсь заменить валюту аббревиатурой GBP на символ £. Я мог бы просто сопоставить что угодно, начиная с GBP, но я бы хотел быть немного более консервативным и искать вокруг него определенные разделители.

>>> import re
>>> text = u'GBP 5 Off when you spend GBP75.00'

>>> re.sub(ur'GBP([\W\d])', ur'£\g<1>', text) # matches GBP with any prefix
u'\xa3 5 Off when you spend \xa375.00'

>>> re.sub(ur'^GBP([\W\d])', ur'£\g<1>', text) # matches at start only
u'\xa3 5 Off when you spend GBP75.00'

>>> re.sub(ur'(\W)GBP([\W\d])', ur'\g<1>£\g<2>', text) # matches whitespace prefix only
u'GBP 5 Off when you spend \xa375.00'

Могу ли я сделать оба последних примера одновременно?

Ответы [ 8 ]

49 голосов
/ 08 февраля 2009

Используйте оператор ИЛИ "|":

>>> re.sub(r'(^|\W)GBP([\W\d])', u'\g<1>£\g<2>', text)
u'\xa3 5 Off when you spend \xa375.00'
32 голосов
/ 08 февраля 2009

\b - граница слова, которая может быть пробелом, началом строки или не буквенно-цифровым символом (\bGBP\b).

6 голосов
/ 08 февраля 2009

Он заменяет GBP, если ему предшествует начало строки или граница слова (которой уже является начало строки), а после GBP следует числовое значение или граница слова:

re.sub(u'\bGBP(?=\b|\d)', u'£', text)

Это устраняет необходимость любых ненужных обратных ссылок с помощью lookahead . Достаточно инклюзивно?

2 голосов
/ 08 февраля 2009

Я думаю, что вы ищете '(^|\W)GBP([\W\d])'

0 голосов
/ 20 апреля 2019

Левая граница пробела - позиция в строке, которая является либо началом строки, либо сразу после символа пробела - может быть выражена с помощью

(?<!\S)   # A negative lookbehind requiring no non-whitespace char immediately to the left of the current position
(?<=\s|^) # A positive lookbehind requiring a whitespace or start of string immediately to the left of the current position
(?:\s|^)  # A non-capturing group matching either a whitespace or start of string 
(\s|^)    # A capturing group matching either a whitespace or start of string

См. Демоверсию regex . Демонстрация Python 3 :

import re
rx = r'(?<!\S)GBP([\W\d])'
text = 'GBP 5 Off when you spend GBP75.00'
print( re.sub(rx, r'£\1', text) )
# => £ 5 Off when you spend £75.00

Обратите внимание, что вы можете использовать \1 вместо \g<1> в шаблоне замены, поскольку нет необходимости в однозначной обратной ссылке, если за ней не следует цифра.

БОНУС: Правая граница пробела может быть выражена с помощью следующих шаблонов:

(?!\S)   # A negative lookahead requiring no non-whitespace char immediately to the right of the current position
(?=\s|$) # A positive lookahead requiring a whitespace or end of string immediately to the right of the current position
(?:\s|$)  # A non-capturing group matching either a whitespace or end of string 
(\s|$)    # A capturing group matching either a whitespace or end of string
0 голосов
/ 08 февраля 2009

Работает в Perl:

$text = 'GBP 5 off when you spend GBP75';
$text =~ s/(\W|^)GBP([\W\d])/$1\$$2/g;
printf "$text\n";

Вывод:

$ 5 off when you spend $75

Обратите внимание, что я предусмотрел, что совпадение должно быть глобальным, чтобы получить все вхождения.

0 голосов
/ 08 февраля 2009

Вы всегда можете обрезать начальные и конечные пробелы из токена перед поиском, если ситуация не соответствует / группируется, когда требуется полная строка.

0 голосов
/ 08 февраля 2009

Да, а почему нет?

re.sub(u'^\W*GBP...

соответствует началу строки, 0 или более пробелов, затем GBP ...

edit : О, я думаю, вы хотите чередование, используйте |:

re.sub(u'(^|\W)GBP...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...