regex@a 替换时 2 参能否实现 lambda 语法

如题,关于正则替换时第二参数能否实现 lambda 语法,这个问题两个月前发帖求助过:" SPL 中使用正则替换的问题 ",苦于没有期待的结果,一直纠结到现在,老是惦记着。干脆再求助一次,恳请 SPL 大佬们给予帮助。

一般的正则替换,只能对匹配的子串做简单的处理,且只能以 string 类型作为替换文本来替换匹配的子串,可以实现的功能比较有限。这也是目前 SPL 中 regex@a 能实现的功能,简单举例如下,比如要把文本串 "abAB" 中的大小写字母交换位置,得到 "AB ab",可以有两种写法实现:

1、常规的捕获分组,用自带的正则属性 $n 来获取第 n 个分组的匹配结果

imagepng

2、SPL 里的正则表达式也可以用命名分组,用 ${名称} 来获取某个命名分组的匹配结果

imagepng

可以看到,这样的正则风格写法自然,没有问题。命名分组在一些语言里 (像 VBA、JS) 是不支持的,但在 SPL 中支持,这是一个小惊喜。不足的地方是,SPL 中也只有 $n 和 ${name}这个分组属性,其它的属性没有,比如以下正则构造属性没有:
1、RegExp.input 或者 $_ 表示目标文本;
2、RegExp.lastMatch 或者 $& 表示表达式匹配的文本;
3、RegExp.leftContext 或者 $` 表示匹配值左侧的文本;
4、RegExp.rightContext 或者 $’ 表示匹配值右侧的文本;
5、RegExp.index 表示匹配值的起始索引

当然,最普遍的功能就是把匹配结果替换成某个指定的文本,regex@a(pattern,replacement),比较遗憾的是,目前 SPL 中二参的 replacement 只支持固定文本或者上述写法,不支持正则委托 (delegate),意思就是,在每次匹配成功时,都会调用方法,对匹配的子串进行处理之后,再作为替换文本返回。此时,匹配子串使用委托方法,可以做任意复杂的处理,因此这种替换功能会非常强大。委托的类型可以是 MatchEvaluator(这里我们不需要这种显式的委托方法),也可以是匿名方法 lambda,在每次匹配成功时调用,也就是说,正则表达式在每次匹配成功时,会得到一个 Match 对象,作为参数传给委托方法,做一定处理后,返回替换文本,替换匹配到的子串。比如,要把文本 "a10b20" 中的数字都乘以 10,返回 "a100b200",期望的写法是:regex@a(“(\\d+)”,(x,y)->string(y*10)) 类似这样的 lambda 语法。

实践中,正则委托的典型应用场景一般可归纳为以下几种:

1、替换子串需进行非 string 类型的处理,如计算;
2、替换子串需经过条件或逻辑判断来决定处理方式;
3、多种条件组合的替换。

可以看到,替换时不仅仅是替换成某个文本,关键是能对匹配的子串进行处理计算,因此,二参能实现匿名函数 lambda 语法就变得不可或缺了。

SPL 中能实现的正则 pattern 还是很强大的,有点类似于 Perl 风格,我挨个试了一下,除了比较高阶的正则递归 (?R) 和平衡组 (?<Close-Open>exp) 不能用,RightToLeft 模式不能用,其它的都能用,像内联匹配模式,支持 (?imnsx-imnsx:) 和(?imnsx-imnsx)两种形式,这个内联匹配模式,最常见的用法就是大小写开关(?i),可以直接写在表达式里,而且可以分段开关;固化分组(?>exp),也有的叫原子组,可用于避免正则回溯陷阱,正则发生回溯时的时间复杂度是 O(2 的 n 次方 -1),效率很低;顺序环视和逆序环视,逆序环视还支持显式变长,这些特性都是其它语言没有的。VBA,JSA 里的正则功能一般,但 JSA 里的正则支持 lambda 语法,Power Query 和 Excel 函数,WPS 函数目前是不支持正则的。

可以说,正则是文本字符的高度抽象,而文本处理的尽头就是正则表达式。当然,正则表达式也不能独立存在,需要编程语言或者工具作为宿主对其提供支持,得益于 JAVA 的强大,我相信 SPL 能根据自身的特点,对其进行一定的剪裁或扩展,这需要大佬们的付出。

以上需求,恳请 SPL 大佬们有空时考虑一下,看能否实现二参的 lambda 语法。

万分感谢!