[从我原来的question跟进,提供更好的说明和链接]
尝试匹配两个符号之间的任何字符(包括换行符,制表符,空格等)。
例如:
foobar89 \ n \ nfoo \ TBAR; '' blah blah blah' 8& ^"''''
需要匹配
'' blah blah blah' 8& ^"'''
和
fjfdaslfdj; '' blah \ n blah \ n \ t \ t blah \ n' 8& ^"'''
需要匹配
'' blah \ n blah \ n \ t \ t blah \ n' 8& ^"''''
我正在测试正则表达式的我的Python代码(从here获取和改编):
import collections
import re
Token = collections.namedtuple('Token', ['typ', 'value', 'line', 'column'])
def tokenize(code):
token_specification = [
('BOTH', r'([\'"]{3}).*?\2'), # for both triple-single quotes and triple-double quotes
('SINGLE', r"('''.*?''')"), # triple-single quotes
('DOUBLE', r'(""".*?""")'), # triple-double quotes
# regexes which match OK
('COM', r'#.*'),
('NEWLINE', r'\n'), # Line endings
('SKIP', r'[ \t]+'), # Skip over spaces and tabs
('MISMATCH',r'.'), # Any other character
]
test_regexes = ['COM', 'BOTH', 'SINGLE', 'DOUBLE']
tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
line_num = 1
line_start = 0
for mo in re.finditer(tok_regex, code):
kind = mo.lastgroup
value = mo.group(kind)
if kind == 'NEWLINE':
line_start = mo.end()
line_num += 1
elif kind == 'SKIP':
pass
elif kind == 'MISMATCH':
pass
else:
if kind in test_regexes:
print(kind, value)
column = mo.start() - line_start
yield Token(kind, value, line_num, column)
f = r'C:\path_to_python_file_with_examples_to_match'
with open(f) as sfile:
content = sfile.read()
for t in tokenize(content):
pass #print(t)
file_with_examples_to_match
所在的位置:
import csv, urllib
class Q():
"""
This class holds lhghdhdf hgh dhghd hdfh ghd fh.
"""
def __init__(self, l, lo, d, m):
self.l= l
self.lo= longitude
self.depth = d
self.m= m
def __str__(self):
# sdasda fad fhs ghf dfh
d= self.d
if d== -1:
d= 'unknown'
m= self.m
if m== -1:
d= 'unknown'
return (m, d, self.l, self.lo)
foobar89foobar; '''blah qsdkfjqsv,;sv
vqùlvnqùv
dqvnq
vq
v
blah blah'8&^"'''
fjfdaslfdj; '''blah blah
blah
'8&^"'''
从this answer开始,我尝试r"('''.*?''')|"r'(""".*?""")
来匹配三重单引号和三重双引号的情况,但没有成功。尝试r'([\'"]{3}).*?\2')
时也一样。
我已经设置了一个online正则表达式测试程序,其中一些正则表达式符合预期,但在上面的代码中它们会失败。
我有兴趣了解Python的正则表达式,所以我很感激一个解决方案(可能是一个有效的正则表达式来对我的代码进行所需的匹配)和一个简短的解释,所以我可以看到我的缺点。 / p>
答案 0 :(得分:1)
你可能错过了让.
匹配换行符的标志
re.finditer(tok_regex, code, flags = re.DOTALL)
在这种情况下输出为
('BOTH', '"""\n This class holds lhghdhdf hgh dhghd hdfh ghd fh.\n """')
('COM', '# sdasda fad fhs ghf dfh\n d= self.d\n if d== -1:\n d= \'unknown\'\n m= self.m\n if m== -1:\n d= \'unknown\'\n\n return (m, d, self.l, self.lo)\n\nfoobar89foobar; \'\'\'blah qsdkfjqsv,;sv\n vq\xc3\xb9lvnq\xc3\xb9v \n dqvnq\n vq\n v\n\nblah blah\'8&^"\'\'\'\nfjfdaslfdj; \'\'\'blah blah\n blah\n \'8&^"\'\'\'')
COM
现在匹配太多,因为.
现在将所有内容都放到文件末尾。如果我们稍微修改这个模式以减少贪心
('COM', r'#.*?$')
我们现在可以使用re.MULTILINE
使其匹配更少
re.finditer(tok_regex, code, flags = re.DOTALL | re.MULTILINE)
现在的输出是
('BOTH', '"""\n This class holds lhghdhdf hgh dhghd hdfh ghd fh.\n """')
('COM', '# sdasda fad fhs ghf dfh')
('BOTH', '\'\'\'blah qsdkfjqsv,;sv\n vq\xc3\xb9lvnq\xc3\xb9v \n dqvnq\n vq\n v\n\nblah blah\'8&^"\'\'\'')
('BOTH', '\'\'\'blah blah\n blah\n \'8&^"\'\'\'')
如果你绝对不想使用旗帜,你可以使用一种&#39; hack&#39;没有.
,因为除了换行符之外,这个元字符几乎可以匹配所有内容。您可以创建一个匹配组,该匹配组将匹配除一个符号之外的所有内容,这很可能不会出现在您要解析的文件中。例如,您可以使用带有ASCII代码0的字符。此类字符的正则表达式为\x00
,相应的模式[^\x00]
将匹配每个符号(甚至是换行符),但ASCII码为0的符号除外(这就是为什么它是一个黑客,你不能没有标志匹配每个符号)。您需要为COM
保留初始正则表达式,对于BOTH
,它将是
('BOTH', r'([\'"]{3})[^\x00]*?\2')
强烈推荐使用正则表达式的是可以解释它们的在线工具,例如regex101
对于更复杂的引用匹配案例,您需要编写解析器。例如,请参阅此Can the csv format be defined by a regex?和此When you should NOT use Regular Expressions?。