python - PyParsing OR 语句

标签 python logging amazon-s3 pyparsing

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

"GET /ligonier-broadcast-media/mp3/rym20110421.mp3 HTTP/1.1"

或者
-

我试过这样的事情:
key = Word(alphas + nums + "/" + "-" + "_" + "." + "?" + "=" + "%" + "&")

uri = Or("-" | Group(
                   Suppress("\"") +
                   http_method +
                   key.setResultsName("request_uri") +
                   http_protocol +
                   Suppress("\"")
               )
      )

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

日志格式无法协商,我们正在消耗我们得到的东西。任何提示将非常感谢。

最佳答案

通常,在 pyparsing 中,Or、And、MatchFirst 和 Each 类很少公开使用。推荐的风格是使用它们类似的运算符重载。在您的情况下,您同时使用这两种形式,这只是在妨碍您。

这是你的表情,稍作整理后:

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

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

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

将解析带有前导 Word(alphas) 的字符串的开头“abc” .我们通常可以通过重新排列替代方案来解决这样的问题,例如:
Word(alphanums) | Word(alphas) | Word(nums)

但并非所有情况都如此容易重构。所以 pyparsing 也支持 Or 表达式,它使用 '^' 运算符定义(我选择它是因为 '^' 让我想起了一对绘图员的分隔线,用于测量长度)。 Or 表达式尝试应用所有给定的替代方案,并选择最长的匹配项。因此,您可以将我的小测试示例编写为:
Word(alphas) ^ Word(nums) ^ Word(alphanums)

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

对于你的 URI 定义,不需要做 Or 匹配。解析器无法将前导“-”与带引号的 HTTP 命令字符串混淆。所以使用 MatchFirst,你已经通过使用“|”运营商,完全够用。

其他一些项目:
  • 不要写"\""在 Python 中,如果你能帮忙的话。正是出于这个原因,Python 支持两种引用字符。使用 '"'反而。反斜杠用于 C 程序员和 Windows 文件名。
  • expr.setResultsName("name")已简化为 expr("name")自 pyparsing 1.4.6 以来。缩短的语法确实有助于提高解析器定义的可读性。
  • 仅当您想在结果中保留某些结构时,或者如果您有一个重复的结构,该结构具有一些带有结果名称的内部表达式时,才使用 Group。对于您的解析器来说不是必需的,只是在结果上添加另一个列表容器包装器,需要额外的 [0]获取解析数据的索引。

  • (如果您确实决定要显式调用 OrAnd 等,请确保传递表达式列表,而不要仅将它们列为表达式构造函数的参数 - 参见 Why is ordered choice in pyparsing failing for my use case?这样的拼写错误是如何把事情搞砸的,这就是为什么我鼓励使用算术运算符来组成你的解析器。)

    关于python - PyParsing OR 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5798994/

    相关文章:

    logging - 从Kubernetes登录到文件

    amazon-web-services - 无法使用已配置的 SQS 策略验证 Cloudformation 中 S3 到 SQS 通知的以下目标配置

    python - Scrapy爬取完成,没有爬取所有启动请求

    logging - 安排特定文件存储在 AWS 的 EBS 卷上

    python - Python 中 epsilon 的值

    python - 如何在Python中异步记录stdout/stderr?

    node.js - 使用 NodeJS 和请求模块以及 aws-sdk 将图像从 Parse 移动到 S3/CloudFront

    java - 使用 SDK 对 AWS S3 存储桶中的对象进行计数时计数不正确

    python - 如何获取QGraphicsItem坐标系中的光标点击位置?

    python - 用 Popen 控制 puttygen