为了帮助创建健壮的正则表达式和语法,以下是一些关于代码布局和可读性、实际匹配内容以及避免常见陷阱的最佳实践。
代码布局§
在没有 :sigspace
副词的情况下,空白在 Raku 正则表达式中并不重要。利用这一点,在需要提高可读性的位置插入空白。此外,在必要时插入注释。
比较非常紧凑的
my
与更易读的
my
作为经验法则,在原子周围和组内使用空白;将量词直接放在原子之后;并将打开和关闭方括号和圆括号垂直对齐。
当你在括号或方括号内使用一系列替换时,请对齐竖线
my
保持简洁§
正则表达式通常比普通代码更简洁。由于它们用很少的代码就能完成很多工作,因此要保持正则表达式的简短。
当你可以命名正则表达式的一部分时,通常最好将其放入一个单独的命名正则表达式中。
例如,你可以从前面的示例中获取浮点数正则表达式
my
并将其分解成各个部分
mymymymy
这很有帮助,尤其是在正则表达式变得更加复杂时。例如,你可能希望在存在指数的情况下使小数点可选。
my
匹配内容§
通常,输入数据格式没有明确的规范,或者程序员不知道规范。在这种情况下,最好对期望的内容持宽松态度,但前提是不能存在任何可能的歧义。
例如,在 ini
文件中
[section]
key=value
节标题内部可以包含什么内容?只允许一个单词可能过于严格。有人可能会写 [two words]
,或者使用连字符等。与其询问内部允许什么,不如反过来问:不允许什么?
显然,不允许出现闭合方括号,因为 [a]b]
会产生歧义。根据相同的论据,应该禁止出现开头的方括号。这让我们得到了
如果只处理一行,这就可以了。但是,如果你要处理整个文件,正则表达式突然解析
[with a newline in between]
这可能不是一个好主意。一个折衷方案是
然后,在后处理中,从节标题中删除前导和尾随空格和制表符。
匹配空白§
:sigspace
副词(或使用 rule
声明符而不是 token
或 regex
)对于隐式解析可能出现在许多地方的空白非常有用。
回到解析 ini
文件的示例,我们有
my
这可能不像我们希望的那样宽松,因为用户可能会在等号周围添加空格。因此,我们可以尝试以下方法
my
但这看起来很笨拙,所以我们尝试其他方法
my
但是等等!值后面的隐式空白匹配会消耗掉所有空白,包括换行符,因此 \n+
没有剩余的内容可以匹配(并且 rule
也禁用了回溯,所以在这里没有用)。
因此,重要的是重新定义隐式空白的定义,使其成为输入格式中不重要的空白。
这通过重新定义令牌 ws
来实现;但是,它只适用于 语法
my =say so IniFormat.parse();
除了将所有正则表达式放入语法中并将其转换为令牌(因为它们不需要回溯)之外,有趣的新部分是
它在隐式空白解析时被调用。当它不在两个单词字符之间(<!ww>
,否定“在单词内”断言)时,它会匹配零个或多个水平空格字符。限制为水平空白很重要,因为换行符(垂直空白)分隔记录,不应该被隐式匹配。
尽管如此,仍然存在一些与空白相关的麻烦。正则表达式 \n+
不会匹配像 "\n \n"
这样的字符串,因为两个换行符之间有一个空格。为了允许这样的输入字符串,请将 \n+
替换为 \n\s*
。