regex@a 替换时 2 参能否实现 lambda 语法
如题,关于正则替换时第二参数能否实现 lambda 语法,这个问题两个月前发帖求助过:" SPL 中使用正则替换的问题 ",苦于没有期待的结果,一直纠结到现在,老是惦记着。干脆再求助一次,恳请 SPL 大佬们给予帮助。
一般的正则替换,只能对匹配的子串做简单的处理,且只能以 string 类型作为替换文本来替换匹配的子串,可以实现的功能比较有限。这也是目前 SPL 中 regex@a 能实现的功能,简单举例如下,比如要把文本串 "abAB" 中的大小写字母交换位置,得到 "AB ab",可以有两种写法实现:
1、常规的捕获分组,用自带的正则属性 $n 来获取第 n 个分组的匹配结果
2、SPL 里的正则表达式也可以用命名分组,用 ${名称} 来获取某个命名分组的匹配结果
可以看到,这样的正则风格写法自然,没有问题。命名分组在一些语言里 (像 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 语法。
万分感谢!
正则表达式难度太大,很多专业程序员都难以掌握。SPL 就简单地把 Java 的正则表达式集成进来了,这个成本很低,也就提供了。Java 没有的本事,SPL 要自己去做,就划不来了。SPL 有自己体系的 Lambda 语法,也塞不进 Java 体系中,而且,也没什么必要。
程序语言的功能,也要考虑性价比,实现它支付什么样的成本,得到什么好处?要做的某件事是不是换一种办法更方便(包括难度更低),不要为了做而做。
正则表达式本身一定程度上就是个失败的设计!它为了解析复杂字串,引入了非常复杂的规则,经常比写一段代码还复杂,以至于人都学不会了,而且它的速度非常慢(因为规则复杂)。正则表达式在现实中的使用率非常低。
看看要用它干什么,SPL 的字串处理方法应该是够的。比如大小写交换位置这种事,用 SPL 写起来可能比正则表达式更容易懂吧。s.split().group@i(islower(~)).rvs().conj().conj().concat()
实在觉得有必要,可以自己基于 Java 实现,SPL 允许程序员用 Java 写个自定义函数补上去,或者直接写个简单的静态方法被 SPL 调用。
谢谢老贼解惑。您说的我完全同意:
1、cost-benifit 是程序设计首先需要考虑的。因为我不在编程的圈子里,想问题的角度跟您不一样,我只是为了实现而实现。但您说的我都理解。
2、正则在实践中的使用率确实很低,而且速度一般,更要命的是不同的宿主提供的正则风格还不一样,这也是其不能普及的原因之一。
我之所以纠结于这个功能,是因为对 SPL 存有幻想,就像我经常说的 SPL 是我目前接触过的最对我口味的,我恨不得市面上所有流行编程语言的特性都能整合到 SPL 中去。我本身是做财务的,但市面上流行的编程语言和数据库,我多少都会一些,就是不会 JAVA,所以,经常麻烦你们,搞一些匪夷所思的想法,确实是存有私心。望大神见谅🙏
有一点希望您能 Agree to disagree,不管咋样,正则始终是文本处理不可或缺的手段,在一些复杂场景中,往往会有化腐朽为神奇的功效。
有了您的解惑和指点,我也就不纠结了。必要的时候,我去学学 JAVA,之前搞帆软报表的时候看过一点 JAVA,自定义函数东拼西凑也能凑出来。
谢谢啦,大神,Happy Weekend! Peace!