我正在编写一个具有自动完成功能的搜索栏,该功能已连接到端点。我正在使用正则表达式来确定我在搜索栏中键入的查询中的"上下文"。这三个上下文是"属性"、"值"和"运算符"。允许的两个运算符是"AND"和"OR"。下面是一个示例查询示例。
颜色:蓝色和尺寸:"女士大号"(<- 多字值或属性名称用引号引起来)
在 Blue 后面放一个空格后,我需要我的正则表达式匹配,如果用户开始键入"A/AN/AND/O/OR",我需要它匹配。一旦他们在运算符后面放了一个空格,我需要它停止匹配。
这是我想出的表达方式。
const contextIsOperator = /[wds"]+: *[wsd"]+ [w]*$/
一旦我在"蓝色"之后放置一个空格,它就会匹配,但与我在此之后放置的所有内容匹配。如果我用 + 替换表达式中的最后一个*
,当我在"Blue"之后放置一个空格并开始手动键入其中一个运算符时,它会起作用,但如果我在"Blue"之后只有一个空格,则不起作用。
我脑子里用文字写的模式是:
- 一个或多个字符/数字/空格/引号的组
- 后跟一个冒号
- 后跟一个可选空格
- 后跟另一组一个或多个字符/数字/空格/引号
- 后跟一个空格(在值之后)
- 后跟一个或多个字符(这是运算符)
如何解决此问题?
将[w]*
更改为仅匹配AND
、OR
或其前缀之一的内容。然后,您可以使用?
将其设置为可选
[ws"]+: *[ws"]+ (A|AN|AND|O|OR)?$
演示
请注意,Size: Women's Large
不会匹配这一点,因为撇号不在w
中;它只匹配字母、数字和下划线。您需要将要在这些字段中允许的任何其他标点字符添加到字符集中。
是,你的语言没有足够的确定性,无法使用正则表达式正确建模。 话虽如此,您可以采取两种方法:
- 要求所有值(
:
之后和运算符之前的内容)括在引号中 - 构建一个简单的状态机,可以更智能地解析数据。 (谷歌有限状态机解析器)
如果选择使用第一种方法,则可以使用以下正则表达式:
^(("?[ws]+"?): ?("[ws']+")( (AND|OR) )?)+$
我会解释不同的组件,但 regex101 已经为我提供了非常好的视觉效果和细节。
编辑:这是最后一个,在这里检查单元测试
const regex = /((("[ws"'']+(?="b))"|[w"'']+):s?(("[ws"'']+(?="b))"|[w"'']+)s(AND|OR)(?=bs))+/
怪物应该匹配(NOTE: QUOTED KEYS/VALUES MUST BE DOUBLE QUOTED
):
Color: Blue AND "Size5":"Women's Large"
"weird KEy":regularvalue OR otherKey: "quoted value"
来吧,试试这个
^(?:"[^"]*"|[^s:]+):[ ](?:"[^"]*"|[^s:]+)[ ](?:A(?:N(?:D(?:[ ](*SKIP)(?!))?)?)?|O(?:R(?:[ ](*SKIP)(?!))?)?)?
https://regex101.com/r/neUQ0g/1
解释
^ # BOS
(?: # Attribute
"
[^"]*
"
|
[^s:]+
)
:
[ ]
(?: # Value
"
[^"]*
"
|
[^s:]+
)
[ ] # Start matching after Attribute: Value + space
(?: # Operator
A
(?:
N
(?:
D
(?: # Stop matching after 'AND '
[ ]
(*SKIP)
(?!)
)?
)?
)?
|
O
(?:
R
(?: # Stop matching after 'OR '
[ ]
(*SKIP)
(?!)
)?
)?
)?