【发布时间】:2014-04-26 02:09:23
【问题描述】:
我正在尝试使用pyparsing 在以下条件下解析带引号的字符串:
- 带引号的字符串可能包含内部引号。
- 我想使用反斜杠来转义内部引号。
- 带引号的字符串可能以反斜杠结尾。
我正在努力定义一个成功的解析器。另外,我开始怀疑 pyparsing 用于此类引用字符串的正则表达式是否正确(请参阅下面的替代正则表达式)。
我是在错误地使用 pyparsing(很可能)还是在 pyparsing 中存在错误?
这是一个演示问题的脚本(注意:忽略此脚本;请关注下面的更新。):
import pyparsing as pp
import re
# A single-quoted string having:
# - Internal escaped quote.
# - A backslash as the last character before the final quote.
txt = r"'ab\'cd\'"
# Parse with pyparsing.
# Does not work as expected: grabs only first 3 characters.
parser = pp.QuotedString(quoteChar = "'", escChar = '\\', escQuote = '\\')
toks = parser.parseString(txt)
print
print 'txt: ', txt
print 'pattern:', parser.pattern
print 'toks: ', toks
# Parse with a regex just like the pyparsing pattern, but with
# the last two groups flipped -- which seems more correct to me.
# This works.
rgx = re.compile(r"\'(?:[^'\n\r\\]|(?:\\.)|(?:\\))*\'")
print
print rgx.search(txt).group(0)
输出:
txt: 'ab\'cd\'
pattern: \'(?:[^'\n\r\\]|(?:\\)|(?:\\.))*\'
toks: ["ab'"]
'ab\'cd\'
更新
感谢您的回复。我怀疑我的问题表述得很糟糕,把事情搞糊涂了,所以让我再试一次。
假设我们正在尝试解析一种使用引用规则的语言,例如 Python。我们希望用户能够定义可以包含内部引号(受反斜杠保护)的字符串,并且我们希望这些字符串能够以反斜杠结尾。这是我们语言的示例文件。请注意,该文件还将解析为有效的 Python 语法,如果我们打印 foo(在 Python 中),输出将是文字值:ab'cd\
# demo.txt
foo = 'ab\'cd\\'
我的目标是使用 pyparsing 来解析这样的语言。有没有办法做到这一点?上面的问题基本上是我在几次尝试失败后最终的结果。以下是我的初步尝试。它失败了,因为末尾有两个反斜杠,而不仅仅是一个。
with open('demo.txt') as fh:
txt = fh.read().split()[-1].strip()
parser = pp.QuotedString(quoteChar = "'", escChar = '\\')
toks = parser.parseString(txt)
print
print 'txt: ', txt
print 'pattern:', parser.pattern
print 'toks: ', toks # ["ab'cd\\\\"]
我想问题在于QuotedString 仅将反斜杠视为引号转义,而 Python 将反斜杠视为更通用的转义。
有没有一种我忽略的简单方法可以做到这一点?我想到的一种解决方法是在事后使用.setParseAction(...) 处理双反斜杠——也许像这样,这似乎有效:
qHandler = lambda s,l,t: [ t[0].replace('\\\\', '\\') ]
parser = pp.QuotedString(quoteChar = "'", escChar = '\\').setParseAction(qHandler)
【问题讨论】:
-
您希望如何解析示例文本?对我来说,这似乎是一个格式错误的引号字符串,因为只有一个未转义的引号。
-
我不确定这是可能的(或至少是实用的)。你打算如何区分
ab\'cd\'和ab\'cd\' <100MB of other text> \'?也就是说,您如何在上下文中知道转义的引号是否是字符串的结尾? -
@Blckknght 我希望以我的正则表达式解析它的方式解析它。
-
@BrenBarn 也许我忽略了一些明显的东西......但是 100MB 的其他文本有什么关系?例如:
txt = r"ab\'cd\' <100MB of other text> \'"时,我的rgx解析文本就好了。 pyparsing 不应该能够对QuotedString对象做类似的事情吗? -
@FMc:看我的回答。基本上,如果你知道你只解析一个字符串,你的正则表达式就可以了。但是,当您实际尝试解析可能包含许多此类分隔字符串的整个文档时,您的方法可能会导致解析混乱。
标签: python regex pyparsing quoting