PyParsing OR语句

Gre*_*reg 3 python logging amazon-s3 pyparsing

这最终会变得非常简单,但我正在尝试匹配两种模式中的一种:

"GET /ligonier-broadcast-media/mp3/rym20110421.mp3 HTTP/1.1"
Run Code Online (Sandbox Code Playgroud)

要么

-
Run Code Online (Sandbox Code Playgroud)

我尝试过这样的事情:

key = Word(alphas + nums + "/" + "-" + "_" + "." + "?" + "=" + "%" + "&")

uri = Or("-" | Group(
                   Suppress("\"") +
                   http_method +
                   key.setResultsName("request_uri") +
                   http_protocol +
                   Suppress("\"")
               )
      )
Run Code Online (Sandbox Code Playgroud)

但它似乎并不匹配.我不确定如何使用Or(),如果我应该是Group(),或者是什么.我知道Group()类中提供的参数如果单独调用,但我真的需要破折号或引用的URI字符串,而不仅仅是一个.

日志格式无法协商,我们正在消耗我们已经给出的内容.任何提示将非常感谢.

Pau*_*McG 19

一般来说,Or,And,MatchFirst和Every类很少用于pyparsing.建议的样式是使用类似的运算符重载.在你的情况下,你正在使用这两种形式,它只是妨碍你.

经过一点清理之后,这是你的表达方式:

key = Word(alphanums + "/-_.?=%&")
QUOT = Suppress('"')
uri = ("-" | QUOT
             + http_method
             + key("request_uri")
             + http_protocol
             + QUOT
      )
Run Code Online (Sandbox Code Playgroud)

Word的参数是表示允许字符集的字符串.如果只使用一个参数(如您的情况),那么该字符串将被解释为可以作为Word的一部分进行解析的字符集.如果给出2个字符串,则第一个表示可接受的初始字符集,第二个表示可接受的正文字符集(在定义类似变量名称时很有用,例如在Python中只允许使用alpha和'_'表示初始字符,但也允许正文中的数字.这将是Word(alphas+'_', alphanums+'_').因为Word的参数只是字符串,不需要单独添加"/" + "-" + "_" + ...,只需将它们组合成一个字符串.

'|' 运算符分隔允许的替代项,生成MatchFirst表达式.它被称为MatchFirst,因为解析器将在第一个给定表达式匹配后停止尝试.因此,如果解析字符串"abc" Word(alphas) | Word(nums),pyparsing甚至不会尝试匹配Word(nums)表达式 - 第一个替代匹配.如果你想要的东西有些重叠,这会变得更加棘手.假设您要匹配字母,字母,字母和字母的单词,并且您想要解析字符串"abc123".这个解析器:

Word(alphas) | Word(nums) | Word(alphanums)
Run Code Online (Sandbox Code Playgroud)

将使用前导解析字符串的开头'abc' Word(alphas).我们通常可以通过重新安排替代方案来解决此类问题,例如:

Word(alphanums) | Word(alphas) | Word(nums)
Run Code Online (Sandbox Code Playgroud)

但并非所有情况都如此容易重构.所以pyparsing也支持Or表达式,使用'^'运算符定义(我之所以选择,因为'^'让我想起了一对绘图员的分隔符,用于测量长度).Or表达式尝试应用所有给定的替代项,并选择最长的匹配项.所以你可以把我的小测试例写成:

Word(alphas) ^ Word(nums) ^ Word(alphanums)
Run Code Online (Sandbox Code Playgroud)

现在pyparsing不会在匹配"abc"时停止,但会尝试所有替代方案,并最终选择第三个替代方案,匹配"abc123",因为它提供了更长的匹配.

对于您的URI定义,不需要进行或匹配.解析器无法将前导' - '与引用的HTTP命令字符串混淆.所以使用MatchFirst,你已经使用'|'完成了 操作员,是完全足够的.

其他一些项目:

  • "\""如果你能提供帮助,请不要用Python 编写.出于这个原因,Python支持引用字符.请'"'改用.反斜杠适用于C程序员和Windows文件名.

  • expr.setResultsName("name")expr("name")pyparsing 1.4.6 已被简化为.缩短的语法确实有助于解析器定义的可读性.

  • 仅当您希望在结果中保留某些结构时,或者如果您的重复结构具有一些带有结果名称的内部表达式时,请使用Group.您的解析器并不是必需的,只需在结果上添加另一个列表容器包装器,需要额外的[0]索引来获取您的解析数据.

(如果决定要显式调用Or,And等等,一定要通过表达式的列表,也不要只列出它们作为参数来表达构造-见为什么下令在选择失败pyparsing我使用如此吗?如何这样一个错字就可以把事情搞得一团糟,这就是为什么我鼓励使用算术运算符来编写解析器.)