正则表达式匹配引号组合之间的任何内容
Regular expression to match anything between combination of quotes
[从我的旧 跟进,提供更好的描述和链接 ]
试图匹配两个符号之间的任何字符(包括换行符、制表符、空格等),包括那些符号。
例如:
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}).*?'), # 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&^"'''
从 开始,我尝试 r"('''.*?''')|"r'(""".*?""")
匹配三重单引号和三重双引号,但均未成功。尝试 r'([\'"]{3}).*?')
.
时相同
我已经设置了一个 online 正则表达式测试器,其中一些正则表达式确实匹配,但在上面的代码中它们失败了。
我有兴趣了解 Python 的正则表达式,所以我希望能有一个解决方案(也许是一个有效的正则表达式来对我的代码进行所需的匹配)和一个简短的解释,以便我可以看到我的缺点。
您可能缺少使 .
也匹配换行符的标志
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&^"\'\'\'')
如果你绝对不想使用标志,你可以使用一种 'hack' 来代替 .
,因为这个元字符几乎匹配所有内容,除了换行符。您可以创建一个匹配组,它将匹配除一个符号以外的所有内容,该符号极不可能出现在您要解析的文件中。例如,您可以使用 ASCII 代码为 0 的字符。此类字符的正则表达式为 \x00
,对应的模式 [^\x00]
将匹配每个符号(甚至换行符),但 ASCII 代码为 0 的符号除外 (这就是为什么它是一个黑客,你无法匹配没有标志的每个符号)。您需要为 COM
保留初始正则表达式,对于 BOTH
则为
('BOTH', r'([\'"]{3})[^\x00]*?')
强烈推荐使用正则表达式的在线工具来解释它们,例如 regex101
对于更复杂的引号匹配情况,您需要编写解析器。例如,参见 Can the csv format be defined by a regex? and this When you should NOT use Regular Expressions?.
[从我的旧
试图匹配两个符号之间的任何字符(包括换行符、制表符、空格等),包括那些符号。
例如:
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}).*?'), # 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&^"'''
从 r"('''.*?''')|"r'(""".*?""")
匹配三重单引号和三重双引号,但均未成功。尝试 r'([\'"]{3}).*?')
.
我已经设置了一个 online 正则表达式测试器,其中一些正则表达式确实匹配,但在上面的代码中它们失败了。
我有兴趣了解 Python 的正则表达式,所以我希望能有一个解决方案(也许是一个有效的正则表达式来对我的代码进行所需的匹配)和一个简短的解释,以便我可以看到我的缺点。
您可能缺少使 .
也匹配换行符的标志
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&^"\'\'\'')
如果你绝对不想使用标志,你可以使用一种 'hack' 来代替 .
,因为这个元字符几乎匹配所有内容,除了换行符。您可以创建一个匹配组,它将匹配除一个符号以外的所有内容,该符号极不可能出现在您要解析的文件中。例如,您可以使用 ASCII 代码为 0 的字符。此类字符的正则表达式为 \x00
,对应的模式 [^\x00]
将匹配每个符号(甚至换行符),但 ASCII 代码为 0 的符号除外 (这就是为什么它是一个黑客,你无法匹配没有标志的每个符号)。您需要为 COM
保留初始正则表达式,对于 BOTH
则为
('BOTH', r'([\'"]{3})[^\x00]*?')
强烈推荐使用正则表达式的在线工具来解释它们,例如 regex101
对于更复杂的引号匹配情况,您需要编写解析器。例如,参见 Can the csv format be defined by a regex? and this When you should NOT use Regular Expressions?.