<p>既然你引用了一些测试,听起来你至少在这个问题上做了些尝试。我假设您已经定义了一个数字,可以是整数或实数-无所谓,您无论如何都要将所有内容转换为float-以及两个数字的分数,可能如下所示:</p>
<pre><code>from pyparsing import Regex, Optional
number = Regex(r"\d+(\.\d*)?").setParseAction(lambda t: float(t[0]))
fraction = number("numerator") + "/" + number("denominator")
fraction.setParseAction(lambda t: t.numerator / t.denominator)
</code></pre>
<p>(注意parse操作的使用,它在解析时执行浮点转换和小数除法。我更喜欢在解析时这样做,当我知道某个东西是一个数字或一个分数或其他任何东西时,而不是稍后返回并筛选一堆碎片字符串,尝试重新创建解析器已经完成的识别逻辑。)</p>
<p>以下是我为您的问题编写的测试用例,由整数、分数、整数和分数组成,使用整数和实数:</p>
^{pr2}$
<p>最后一步是如何定义可以是单个数字、分数或单个数字和分数的分数表达式。在</p>
<p>由于pyparsing是从左到右的,它不像regexen那样执行回溯。所以这个表达式不会很好用:</p>
<pre><code>fractExpr = Optional(number) + Optional(fraction)
</code></pre>
<p>要将可能来自数字和分数部分的数值相加,请添加以下解析操作:</p>
<pre><code>fractExpr.setParseAction(lambda t: sum(t))
</code></pre>
<p>我们的测试打印出来:</p>
<pre><code>1 [1.0]
1.0 [1.0]
1/2 [1.0]
1.0/2.0 [1.0]
1 1/2 [1.5]
1.0 1/2 [1.5]
1.0 1.0/2.0 [1.5]
</code></pre>
<p>对于测试用例<code>1/2</code>,它本身只包含一个分数,前导分子与<code>Optional(number)</code>项相匹配,但这只剩下“/2”,它与^{<cd3>不匹配,幸运的是,由于第二项是可选的,所以它“通过”,但它并不是真正做我们想要的。在</p>
<p>我们需要使fractextpr更聪明一点,让它先查找一个单独的分数,因为在一个单独的数字和一个分数的前导分子之间存在着潜在的混淆。最简单的方法是将fractextpr设为:</p>
<pre><code>fractExpr = fraction | number + Optional(fraction)
</code></pre>
<p>现在有了这个变化,我们的测试结果会更好:</p>
<pre><code>1 [1.0]
1.0 [1.0]
1/2 [0.5]
1.0/2.0 [0.5]
1 1/2 [1.5]
1.0 1/2 [1.5]
1.0 1.0/2.0 [1.5]
</code></pre>
<p>pyparsing有几个典型的陷阱,这就是其中之一。请记住,pyparsing只执行您告诉它的lookahead,否则它只是直接从左到右的解析。在</p>