给定一个文本文件,我要匹配的字符由单引号分隔,但可能有零个或一个转义单引号,以及零个或多个制表符和换行符(未转义) - 我想匹配只有文字.例:
menu_item = 'casserole';
menu_item = 'meat
loaf';
menu_item = 'Tony\'s magic pizza';
menu_item = 'hamburger';
menu_item = 'Dave\'s famous pizza';
menu_item = 'Dave\'s lesser-known
gyro';
Run Code Online (Sandbox Code Playgroud)
我想只抓取文本(和空格),忽略标签/换行符 - 我实际上并不关心转义的报价是否出现在结果中,只要它不影响匹配:
casserole
meat loaf
Tonys magic pizza
hamburger
Daves famous pizza
Dave\'s lesser-known gyro # quote is okay if necessary.
Run Code Online (Sandbox Code Playgroud)
我已设法创建一个几乎完成它的正则表达式- 它处理转义的引号,但不处理换行符:
menuPat = r"menu_item = \'(.*)(\\\')?(\t|\n)*(.*)\'"
for line in inFP.readlines():
m = re.search(menuPat, line)
if m is not None:
print m.group()
Run Code Online (Sandbox Code Playgroud)
肯定有大量的正则表达式问题 - 但大多数都使用Perl,如果有一个可以做我想要的,我无法弄明白:)因为我使用的是Python,我不在乎如果它分布在多个组中,则很容易重新组合它们.
一些答案已经说过要使用代码来解析文本.虽然我确信我能做到这一点 - 我已经非常接近正在使用正则表达式:)而且它看起来应该是可行的.
更新:我刚刚意识到我正在使用Python readlines()来获取每一行,这显然正在分解传递给正则表达式的行.我正在考虑重写它,但是关于那部分的任何建议也会非常有帮助.
rid*_*ner 12
这个经过测试的脚本可以解决问题:
import re
re_sq_long = r"""
# Match single quoted string with escaped stuff.
' # Opening literal quote
( # $1: Capture string contents
[^'\\]* # Zero or more non-', non-backslash
(?: # "unroll-the-loop"!
\\. # Allow escaped anything.
[^'\\]* # Zero or more non-', non-backslash
)* # Finish {(special normal*)*} construct.
) # End $1: String contents.
' # Closing literal quote
"""
re_sq_short = r"'([^'\\]*(?:\\.[^'\\]*)*)'"
data = r'''
menu_item = 'casserole';
menu_item = 'meat
loaf';
menu_item = 'Tony\'s magic pizza';
menu_item = 'hamburger';
menu_item = 'Dave\'s famous pizza';
menu_item = 'Dave\'s lesser-known
gyro';'''
matches = re.findall(re_sq_long, data, re.DOTALL | re.VERBOSE)
menu_items = []
for match in matches:
match = re.sub('\s+', ' ', match) # Clean whitespace
match = re.sub(r'\\', '', match) # remove escapes
menu_items.append(match) # Add to menu list
print (menu_items)
Run Code Online (Sandbox Code Playgroud)
这是正则表达式的简短版本:
'([^'\\]*(?:\\.[^'\\]*)*)'
使用Jeffrey Friedl的"展开循环"效率技术优化了这个正则表达式.(有关详细信息,请参阅:掌握正则表达式(第3版)).
请注意,上面的正则表达式相当于下面的正则表达式(在大多数NFA正则表达式实现中更常见,但速度要慢得多):
'((?:[^'\\]|\\.)*)'
这应该可以做到:
menu_item = '((?:[^'\\]|\\')*)'
Run Code Online (Sandbox Code Playgroud)
这里该部分匹配除and或文字(?:[^'\\]|\\')*之外的任何字符的任何序列。前一个表达式还允许换行符和制表符,然后您需要将其替换为单个空格。'\\'[^'\\]