使用正则表达式进行字符串掩码和偏移
我有一个字符串,想用正则表达式来显示指定数量的单词,给定一个偏移量。比如说,我有以下这个字符串:
"The quick, brown fox jumps over the lazy dog."
我想每次显示3个单词:
偏移量 0
: "The quick, brown"
偏移量 1
: "quick, brown fox"
偏移量 2
: "brown fox jumps"
偏移量 3
: "fox jumps over"
偏移量 4
: "jumps over the"
偏移量 5
: "over the lazy"
偏移量 6
: "the lazy dog."
我在用Python,并且使用了以下这个简单的正则表达式来检测3个单词:
>>> import re
>>> s = "The quick, brown fox jumps over the lazy dog."
>>> re.search(r'(\w+\W*){3}', s).group()
'The quick, brown '
但是我不知道怎么才能显示下一个3个单词,而不是开头的那些。我需要保留标点符号。
4 个回答
不需要用正则表达式
>>> s = "The quick, brown fox jumps over the lazy dog."
>>> for offset in range(7):
... print 'offset {0}: "{1}"'.format(offset, ' '.join(s.split()[offset:][:3]))
...
offset 0: "The quick, brown"
offset 1: "quick, brown fox"
offset 2: "brown fox jumps"
offset 3: "fox jumps over"
offset 4: "jumps over the"
offset 5: "over the lazy"
offset 6: "the lazy dog."
一种方法是把字符串分开,然后选择其中的一部分:
words = re.split(r"\s+", s)
for i in range(len(words) - 2):
print ' '.join(words[i:i+3])
当然,这种方法假设你在单词之间只有一个空格,或者你不在乎所有的空白字符都被压缩成一个空格。
前缀匹配选项
你可以通过使用一个可变前缀的正则表达式来跳过前面 offset
个单词,并将单词三元组捕获到一个组里。
比如可以这样写:
import re
s = "The quick, brown fox jumps over the lazy dog."
print re.search(r'(?:\w+\W*){0}((?:\w+\W*){3})', s).group(1)
# The quick, brown
print re.search(r'(?:\w+\W*){1}((?:\w+\W*){3})', s).group(1)
# quick, brown fox
print re.search(r'(?:\w+\W*){2}((?:\w+\W*){3})', s).group(1)
# brown fox jumps
我们来看看这个模式:
_"word"_ _"word"_
/ \ / \
(?:\w+\W*){2}((?:\w+\W*){3})
\_____________/
group 1
这个模式的意思是:匹配 2
个单词,然后把它们捕获到组 1 中,再匹配 3
个单词。
这里的 (?:...)
结构是用来分组重复的,但它不会捕获内容。
参考资料
关于“单词”模式的说明
需要说明的是,\w+\W*
作为“单词”模式并不是一个好的选择,下面的例子就能说明这一点:
import re
s = "nothing"
print re.search(r'(\w+\W*){3}', s).group()
# nothing
这里并没有 3 个单词,但正则表达式还是能匹配,因为 \W*
允许匹配空字符串。
也许更好的模式是这样的:
\w+(?:\W+|$)
也就是说,一个 \w+
后面跟着一个 \W+
或者字符串的结尾 $
。
捕获前瞻选项
正如 Kobi 在评论中提到的,这个选项更简单,因为你只需要一个静态模式。它使用 findall
来捕获所有匹配项(查看 ideone.com):
import re
s = "The quick, brown fox jumps over the lazy dog."
triplets = re.findall(r"\b(?=((?:\w+(?:\W+|$)){3}))", s)
print triplets
# ['The quick, brown ', 'quick, brown fox ', 'brown fox jumps ',
# 'fox jumps over ', 'jumps over the ', 'over the lazy ', 'the lazy dog.']
print triplets[3]
# fox jumps over
这个方法的工作原理是,它在零宽度的单词边界 \b
上匹配,使用前瞻来捕获 3 个“单词”到组 1 中。
______lookahead______
/ ___"word"__ \
/ / \ \
\b(?=((?:\w+(?:\W+|$)){3}))
\___________________/
group 1