Python正则表达式匹配Ledger / hledger帐户日记帐分录

时间:2017-07-23 13:06:21

标签: python regex

我正在用Python编写程序来解析Ledger / hledger日志文件。

我在提出一个正则表达式方面遇到了问题,我确信这很简单。我想解析一个表格的字符串:

expenses:food:food and wine 20.99

并捕获帐户部分(冒号之间,允许任何空格),无论子帐户数量多少,以及组中的总数。子帐户名的最后一个字符与价格数字之间可以有任意数量的空格。

expenses:food:wine:speciality 19.99也是允许的(子帐户中没有空格)。

到目前为止,我已经(\S+):|(\S+ \S+):|(\S+ (?!\d))|(\d+.\d+),不允许任何数量的子帐户和可能的空格。我不认为我希望在那里有OR个运算符,因为这将与其他正则表达.join()连接作为解析函数的一部分。

非常感谢任何帮助。

感谢。

2 个答案:

答案 0 :(得分:0)

您可以使用以下内容:

((?:[^\s:]+)(?:\:[^\s:]+)*)\s*(\d+\.\d+)

现在我们可以使用:

s = 'expenses:food:wine:speciality       19.99'
rgx = re.compile(r'((?:[^\s:]+)(?:\:[^\s:]+)*)\s*(\d+\.\d+)')
mat = rgx.match(s)
if mat:
    categories,price = mat.groups()
    categories = categories.split(':')

现在categories将是一个包含类别的列表,price是一个包含价格的字符串。对于您的样本输入,这给出:

>>> categories
['expenses', 'food', 'wine', 'speciality']
>>> price
'19.99'

答案 1 :(得分:0)

你根本不需要正则表达式,原生str.split()绰绰有余:

def split_ledger(line):
    entries = line.split(":")  # first split all the entries
    last = entries.pop()  # take the last entry
    return entries + last.rsplit(" ", 1)  # split on last space and return all together

print(split_ledger("expenses:food:food and wine            20.99"))
# ['expenses', 'food', 'food and wine           ', '20.99']
print(split_ledger("expenses:food:wine:speciality       19.99"))
# ['expenses', 'food', 'wine', 'speciality      ', '19.99']

或者,如果您不想要任何条目中的前导/尾随空格:

def split_ledger(line):
    entries = [e.strip() for e in line.split(":")]
    last = entries.pop()
    return entries + [e.strip() for e in last.rsplit(" ", 1)]

print(split_ledger("expenses:food:food and wine            20.99"))
# ['expenses', 'food', 'food and wine', '20.99']
print(split_ledger("expenses:food:wine:speciality       19.99"))
# ['expenses', 'food', 'wine', 'speciality', '19.99']