将单词定义为连续的字符块
pyparsing definition of a word as contiguous block of chars
我正在尝试从以下示例行中提取 ID 和数据。
我将 id 定义为包含字母数字和一些其他字符但不包括逗号的东西。我希望 pyparsing 不会将数据的数字 1 作为 id 的一部分,因为数据是连续的块,其中包括逗号,并且逗号被排除在 id 之外。 pyparsing 不应该拒绝整个数据部分作为 id,因为该连续数据块包含 id 部分中未定义的其他字符吗?我的期望是规则适用于整个单词而不是单词
joinTokensViaSpace = lambda tokens: " ".join(" ".join(t.split()) for t in tokens)
parser= OneOrMore(Word(alphanums+'-/.'))('id').setParseAction(joinTokensViaSpace) + Word(nums+',.()')('data')
parser.parseString(' XXX Y/123 1,234.567890')
输出我得到
(['XXX Y/1231', ',234.567890'], {'data': [(',234.567890', 1)], 'id': [('XXX Y/1231', 0)]})
我期望的输出
(['XXX Y/123', '1,234.567890'], {'data': [('1,234.567890', 1)], 'id': [('XXX Y/123', 0)]})
一般来说 Word
通常会在空格上进行解析,但并不像您所发现的那样得到保证。我尝试稍微更改您的解析器以添加 Word
's optional asKeyword=True
argument, and also using Regex
with surrounding \b
markers, but in both cases, the ',' in 1,234.567890
满足正常的分词行为。
最简单的解决方案是在匹配 Word(alphanums+'-/.')
:
之前,在 OneOrMore
中插入否定前瞻
number = Word(nums+',.()')
parser= OneOrMore(~number + Word(alphanums+'-/.'))('id')\
.setParseAction(joinTokensViaSpace) + number('data')
这样,在开始另一个 Word
之前,解析器首先检查它是否处于潜在的 number
,只有在没有的情况下才继续。通过此更改,解析后的输出将如您所愿。 (也许我应该向 OneOrMore
和 ZeroOrMore
添加一个 stopOn
参数,例如 OneOrMore(Word(alphanums+'-/.'), stopOn=number)
- 这对于 pyparsing 开发人员来说确实是一个非常常见的陷阱。)
我还看到您正在使用结果名称 - 这是一个养成的好习惯。既然你有它们,我建议你使用 dump()
作为检查 parseString
.
返回的 ParseResults
结构的最佳工具
result = parser.parseString(' XXX Y/123 1,234.567890')
print result.dump()
打印
['XXX Y/123', '1,234.567890']
- data: 1,234.567890
- id: XXX Y/123
我正在尝试从以下示例行中提取 ID 和数据。 我将 id 定义为包含字母数字和一些其他字符但不包括逗号的东西。我希望 pyparsing 不会将数据的数字 1 作为 id 的一部分,因为数据是连续的块,其中包括逗号,并且逗号被排除在 id 之外。 pyparsing 不应该拒绝整个数据部分作为 id,因为该连续数据块包含 id 部分中未定义的其他字符吗?我的期望是规则适用于整个单词而不是单词
joinTokensViaSpace = lambda tokens: " ".join(" ".join(t.split()) for t in tokens)
parser= OneOrMore(Word(alphanums+'-/.'))('id').setParseAction(joinTokensViaSpace) + Word(nums+',.()')('data')
parser.parseString(' XXX Y/123 1,234.567890')
输出我得到
(['XXX Y/1231', ',234.567890'], {'data': [(',234.567890', 1)], 'id': [('XXX Y/1231', 0)]})
我期望的输出 (['XXX Y/123', '1,234.567890'], {'data': [('1,234.567890', 1)], 'id': [('XXX Y/123', 0)]})
一般来说 Word
通常会在空格上进行解析,但并不像您所发现的那样得到保证。我尝试稍微更改您的解析器以添加 Word
's optional asKeyword=True
argument, and also using Regex
with surrounding \b
markers, but in both cases, the ',' in 1,234.567890
满足正常的分词行为。
最简单的解决方案是在匹配 Word(alphanums+'-/.')
:
OneOrMore
中插入否定前瞻
number = Word(nums+',.()')
parser= OneOrMore(~number + Word(alphanums+'-/.'))('id')\
.setParseAction(joinTokensViaSpace) + number('data')
这样,在开始另一个 Word
之前,解析器首先检查它是否处于潜在的 number
,只有在没有的情况下才继续。通过此更改,解析后的输出将如您所愿。 (也许我应该向 OneOrMore
和 ZeroOrMore
添加一个 stopOn
参数,例如 OneOrMore(Word(alphanums+'-/.'), stopOn=number)
- 这对于 pyparsing 开发人员来说确实是一个非常常见的陷阱。)
我还看到您正在使用结果名称 - 这是一个养成的好习惯。既然你有它们,我建议你使用 dump()
作为检查 parseString
.
ParseResults
结构的最佳工具
result = parser.parseString(' XXX Y/123 1,234.567890')
print result.dump()
打印
['XXX Y/123', '1,234.567890']
- data: 1,234.567890
- id: XXX Y/123