python - 云雀语法:转义字符串正则表达式如何工作?
问题描述
Lark 解析器预定义了一些常见的终端,包括一个字符串。定义如下:
_STRING_INNER: /.*?/
_STRING_ESC_INNER: _STRING_INNER /(?<!\\)(\\\\)*?/
ESCAPED_STRING : "\"" _STRING_ESC_INNER "\""
我明白_STRING_INNER
。我也明白ESCAPED_STRING
是怎么组成的。但我真的不明白的是_STRING_ESC_INNER
。
如果我正确阅读了正则表达式,它只是说,每当我找到两个连续的文字反斜杠时,它们之前一定不能有另一个文字反斜杠?
如何将这两者组合成一个正则表达式?
并且不要求语法只允许字符串数据中的转义双引号吗?
解决方案
预赛:
.*?
非贪婪匹配,意味着.
(任何符号)的最短可能重复次数。这只有在后面跟着其他东西时才有意义。因此.*?X
on inputAAXAAX
将仅匹配AAX
部分,而不是一直扩展到最后一个X
.(?<!...)
是一个“否定的后视断言”(链接):“如果字符串中的当前位置之前没有匹配 ....,则匹配”。所以.*(?<!X)Y
会匹配AY
但不是XY
。
将此应用于您的示例:
ESCAPED_STRING
:规则说:“匹配"
,然后_STRING_ESC_INNER
,然后"
再匹配”。_STRING_INNER
:匹配任何符号的最短可能重复次数。如前所述,这仅在考虑其后的正则表达式时才有意义。_STRING_ESC_INNER
:我们希望它匹配不包含右引号的最短字符串。也就是说,对于一个输入"abc"xyz"
,我们想要匹配"abc"
,而不是同时消耗xyz"
部分。但是,我们必须确保 the"
确实是一个结束引号,因为它本身不应该被转义。所以对于 input"abc\"xyz"
,我们不想只匹配"abc\"
,因为\"
被转义了。我们观察到关闭"
必须直接在偶数之前\
(零是偶数)。所以没问题"
,没问题\\"
,没问题\\\\"
等。但是只要"
前面有奇数个\
,这意味着 the"
并不是真正的结束引号。(\\\\)
匹配\\
。上面说“以前的(?<!\\)
位置不应该有\
”。所以组合的(?<!\\)(\\\\)
意思是“匹配\\
,但前提是它前面没有\
”。然后下面
*?
会尽可能少地重复这个,这再次只有在考虑到后面出现的正则表达式时才有意义,这是"
来自ESCAPED_STRING
规则(可能的混淆点:the\"
inESCAPED_STRING
指的是"
我们实际输入中的文字想要匹配,与输入中\\\\
引用的方式相同\\
)。所以意味着“匹配后面跟不前面(?<!\\)(\\\\)*?\"
的最短数量。换句话说,只匹配前面有偶数个(包括大小为0的块)。\\
"
\
(?<!\\)(\\\\)*?\"
"
\
现在将它与前面
_STRING_INNER
的 结合起来,_STRING_ESC_INNER
规则然后说:匹配第一个"
前面有偶数个\
,换句话说,第一个"
本身\
没有转义的。
推荐阅读
- android - Set Text edittext activity from another class android
- c# - da=填充(ds);asp.net中'='附近的错误
- wpf - WPF DataGrid ComboBoxColumn 未更新绑定数据
- netbeans - Netbeans + Codename One - 避免导入不适合 CN1 的包或类
- java - 改进 kafka 流的最佳实践是什么
- ffmpeg - ffmpeg:无法打开 libx265 编码器。初始化输出流 0:0 时出错——打开输出流 #0:0 的编码器时出错
- javascript - 如何使用 jquery SOAP 从 jquery 消费 SOAP XML?
- c# - CrystalQuartz 在作为 Windows 服务运行时不工作
- java - 尝试在单击时更改按钮名称
- react-native - highcharts事件加载函数中的访问状态变量