代码之家  ›  专栏  ›  技术社区  ›  Dave

在pyparsing中使用QuotedString

  •  4
  • Dave  · 技术社区  · 11 年前

    我在理解如何构建 pyparsing 解析器。步骤是:1)通过组合ParserElement的子类来构建解析器,2)使用解析器来解析字符串。

    以下示例工作正常:

    from pyparsing import Word, Literal, alphas, alphanums, delimitedList, QuotedString
    
    name = Word(alphas+"_", alphanums+"_")
    field = name
    fieldlist = delimitedList(field)
    doc = Literal('<Begin>') + fieldlist + Literal('**End**')
    
    dstring = '<Begin>abc,de34,f_o_o**End**'
    print(doc.parseString(dstring))
    

    产生预期的令牌序列:

    ['<Begin>', 'abc', 'de34', 'f_o_o', '**End**']
    

    但是(例如),类QuotedString不接受ParserElement作为参数,因此它不能用于构建解析器。我希望在上面的示例中使用它,例如:

    name = Word(alphas+"_", alphanums+"_")
    field = QuotedString(name)     ### Wrong: doesn't allow "name" as an argument
    fieldlist = delimitedList(field)
    

    要解析以下形式的文档:

    dstring = '<Begin>"abc", "de34", "f_o_o"**End**'
    

    但是,既然它不能以这种方式使用,那么在构造一个引用字符串列表的解析器时包含QuotedString的正确语法是什么?

    ==========编辑============

    请参阅下面的答案。。。

    2 回复  |  直到 11 年前
        1
  •  4
  •   Dave    11 年前

    QuotedString不能用于此任务。但是OR函数可以实现相同的效果-允许不同形式的引号,同时保留分析引号中包含的字符串的有效性的能力。以下代码执行此操作:

    from pyparsing import Word, Literal, alphas, alphanums, delimitedList
    from pyparsing import Group, QuotedString, ParseException, Suppress
    
    name = Word(alphas+"_", alphanums+"_")
    field = Suppress('"') + name + Suppress('"') ^ \    # double quote
            Suppress("'") + name + Suppress("'") ^ \    # single quote
            Suppress("<") + name + Suppress(">") ^ \    # html tag
            Suppress("{{")+ name + Suppress("}}")       # django template variable
    fieldlist = Group(delimitedList(field))
    doc = Literal('<Begin>') + fieldlist + Literal('**End**')
    
    dstring = [
        '<Begin>"abc","de34","f_o_o"**End**',      # Good
        '<Begin><abc>,{{de34}},\'f_o_o\'**End**',  # Good
        '<Begin>"abc",\'de34","f_o_o\'**End**',    # Bad - mismatched quotes
        '<Begin>"abc","de34","f_o#o"**End**',      # Bad - invalid identifier
    ]
    
    for ds in dstring:
        print(ds)
        try:
            print('  ', doc.parseString(ds))
        except ParseException as err:
            print(" "*(err.column-1) + "^")
            print(err)
    

    这会产生所需的输出,接受两个好的测试字符串,拒绝两个坏的测试字符串:

    <Begin>"abc","de34","f_o_o"**End**
       ['<Begin>', ['abc', 'de34', 'f_o_o'], '**End**']
    <Begin><abc>,{{de34}},'f_o_o'**End**
       ['<Begin>', ['abc', 'de34', 'f_o_o'], '**End**']
    <Begin>"abc",'de34","f_o_o'**End**
                ^
    Expected "**End**" (at char 12), (line:1, col:13)
    <Begin>"abc","de34","f_o#o"**End**
                       ^
    Expected "**End**" (at char 19), (line:1, col:20)
    

    感谢Paul的所有帮助和制作如此酷的包装。

        2
  •  1
  •   PaulMcG    11 年前

    我想您只是对如何使用QuotedString有点困惑。传递给QuotedString的参数为 需要在引号内的字符串-它是用作引号字符的字符。通过这种方式,您可以定义使用“*”作为引号、使用“=”作为引号或使用“<”的带引号字符串和“>”开始和结束引号字符。在您的示例中,只需对字段使用以下定义:

    field = QuotedString('"')
    

    此外,不要害怕使用python的内置help()方法来访问类、模块、方法等的文档字符串。

    编辑:

    QuotedString('X') 作语法分析 "X" ,它解析 X some characters inside matching characters X .

    以下是您的完整(工作)示例程序:

    from pyparsing import QuotedString, delimitedList, Group
    
    dstring = '<Begin>"abc", "de34", "f_o_o"**End**'
    field = QuotedString('"')
    parser = "<Begin>" + Group(delimitedList(field)) + "**End**"
    
    print(parser.parseString(dstring))
    

    这是我的指纹:

    ['<Begin>', ['abc', 'de34', 'f_o_o'], '**End**']
    

    如果复制/粘贴此示例并运行它后出现异常, 发布完整的异常。

    更多示例:

    starQuoteString = QuotedString('*')
    eqQuoteString = QuotedString('=')
    tildeQuoteString = QuotedString('~')
    angleQuoteString = QuotedString('<', endQuoteChar='>')
    
    fullSample = starQuoteString + eqQuoteString + tildeQuoteString + angleQuoteString
    
    print fullSample.parseString("""
        *a string quoted with stars*
        =a very long quoted string, contained within equal signs=
        ~not a very long string at all~<another quoted string on the same line>
        """)
    

    打印:

    ['a string quoted with stars', 'a very long quoted string, contained within equal signs', 'not a very long string at all', 'another quoted string on the same line']
    

    您甚至不限于单个字符。你可以使用 QuotedString('**') 解析你的结束语 **End** ,但这也可以接受 **The End** **Finis** **That's all folks!** .