正则表达式: match start 或空格

正则表达式可以匹配空格 或者作为字符串的开头吗?

我想用一个符号代替货币的缩写 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'

我能同时做后两个示例吗?

60455 次浏览

\b is word boundary, which can be a white space, the beginning of a line or a non-alphanumeric symbol (\bGBP\b).

Yes, why not?

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

matches the start of the string, 0 or more whitespaces, then GBP...

edit: Oh, I think you want alternation, use the |:

re.sub(u'(^|\W)GBP...

You can always trim leading and trailing whitespace from the token before you search if it's not a matching/grouping situation that requires the full line.

This replaces GBP if it's preceded by the start of a string or a word boundary (which the start of a string already is), and after GBP comes a numeric value or a word boundary:

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

This removes the need for any unnecessary backreferencing by using a lookahead. Inclusive enough?

Use the OR "|" operator:

>>> re.sub(r'(^|\W)GBP([\W\d])', u'\g<1>£\g<2>', text)
u'\xa3 5 Off when you spend \xa375.00'

I think you're looking for '(^|\W)GBP([\W\d])'

It works in Perl:

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

The output is:

$ 5 off when you spend $75

Note that I stipulated that the match should be global, to get all occurrences.

A left-hand whitespace boundary - a position in the string that is either a string start or right after a whitespace character - can be expressed with

(?<!\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

See a regex demo. Python 3 demo:

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

Note you may use \1 instead of \g<1> in the replacement pattern since there is no need in an unambiguous backreference when it is not followed with a digit.

BONUS: A right-hand whitespace boundary can be expressed with the following patterns:

(?!\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