使用StringStart()和StringEnd()PyParsing的searchString

时间:2017-10-30 13:04:47

标签: python pyparsing

我试图通过以下测试:

from pyparsing import Word, nums, StringStart, StringEnd
import pytest

def get_square_feet(string):
    area = Word(nums+",")("area").setParseAction(lambda s, l, t: [int(t[0].replace(',', ''))])
    expression = StringStart() + area + "sqft" + StringEnd()
    return expression.parseString(string).get("area")

def test_get_square_feet():
    assert get_square_feet("800 sqft") == 800
    assert get_square_feet("9,000 sqft") == 9000

def test_get_square_feet_with_prefix():
    assert get_square_feet("size: 12,000 sqft") is None

if __name__ == "__main__":
    pytest.main([__file__])

然而,第二次测试失败,因为它导致ParseError。相反,我想使用searchString,但如果我在parseString函数中将searchString替换为get_square_feet,我也会收到错误,因为函数返回{{1 }}。有人能指出我这里有什么问题吗?

3 个答案:

答案 0 :(得分:2)

这是使用pyparsing的相应代码,捕获ParseException:

from pyparsing import Word, nums, StringStart, StringEnd, ParseException

def get_square_feet(string):
    area = Word(nums+",")("area").setParseAction(lambda s, l, t: [int(t[0].replace(',', ''))])
    expression = StringStart() + area + "sqft" + StringEnd()
    try:
        return expression.parseString(string).get("area")
    except ParseException:
        return None

答案 1 :(得分:1)

这是一个使用parsy的解决方案,它在许多方面类似于pyparsing,但具有更好的接口和实现IMO。

from parsy import regex

def get_square_feet(s):
    area = regex(r'[0-9,]+').map(lambda s: int(s.replace(',', '')))
    return (area << string(" sqft") | regex('.*').result(None)).parse(s)

在这里,我们使用|组合器回退到接受任何内容的正则表达式,然后根据需要生成None。您也可以通过捕获ParseError异常并在这种情况下返回None来实现它。

答案 2 :(得分:0)

以下是使用正则表达式传递测试的get_square_feet的实现:

def get_square_feet(string):
    match = re.match(r'^([\d,]+) sqft$', string)
    return int(match.groups()[0].replace(',', '')) if match else None

原则上,PyParsing应该比正则表达式更容易使用,所以我仍然对使用PyParsing的解决方案感兴趣。