1

我正在使用云雀,但不知道如何匹配所有玩家的名字,因为他们可能对云雀规则很复杂?

示例模式是"Seat {number}: {player} ({chips} in chips)",我也想要每一行的所有值。

from lark import Lark, lexer
gram = r"""
start: seats+

seats: "Seat " seat_position player table_chips is_sitting_out? SPACE? NL
seat_position: NUMBER
is_sitting_out: " is sitting out"
table_chips: "(" chips " in chips"  (", " chips " bounty")? ")"
player: STRING_INNER
chips: "$"? (DECIMAL | NUMBERS)

NUMBERS: /[0-9]/+
NUMBER: /[0-9]/
DECIMAL: NUMBERS "." NUMBERS
SPACE: " "+
STRING_INNER: ": " /.*?/ " " 

CR : /\r/
LF : /\n/
NL: (CR? LF)+
"""
data = r"""Seat 1: Ruzzka(Rus) (1200 in chips)
Seat 1: Dladik Rzs38 (1200 in chips)
Seat 1: slum ^o_o^ (1200 in chips)
Seat 1: é=mc² (1200 in chips)
Seat 1: {’O_0`}/(nh) (1200 in chips)
Seat 1: °ÆND0c42Z4y° (1200 in chips)
Seat 1: $ salesovish (1200 in chips)
"""
parser = Lark(gram)
tree = parser.parse(data)
print(tree.pretty())
4

1 回答 1

1

问题是名称结尾显然没有真正的规则,因此很难解析它,因为 Lark 大多是非回溯高速的。

我实际上猜想直接在每一行上使用正则表达式会更容易,除非您还需要解析比您在此处显示的更复杂的结构。但是 Lark 能够处理这种任意内容,例如 here,但性能损失很大。

这里没有百灵鸟的解决方案:

import re

regex = re.compile(r"Seat\s*(?P<number>\d+)\s*:\s*(?P<player>[^\n]+?)\s+\((?P<chips>\d+) in chips\)")

seats = []
for line in data.splitlines():
    match = regex.match(line)
    if match is not None:
        values = match.groupdict()
        seats.append((values["number"], values["player"], values["chips"]))

print(seats)

从您的语法看来,您实际上需要提取更多信息(例如is_sitting_outbounty)。为此,您可以将正则表达式稍微更改为:

Seat\s*(?P<number>\d+)\s*:\s*(?P<player>[^\n]+?)\s+\((?P<chips>\d+) in chips\s*(?:,\s*(?P<bounty>\d+)\s*bounty)?\)(?P<is_sitting_out> is sitting out)?

您可以通过 来检查玩家是否坐在外面values['is_sitting_out'] is not Nonevalues['bounty']如果没有赏金,则为 None。

于 2021-11-29T21:17:37.810 回答