perl6正则表达式匹配连接&&

lis*_*tor 8 regex match perl6 raku

如果连接中的所有部分匹配相同的子字符串而不是整个字符串,则Perl6正则表达式匹配连接&&返回True:

> my $a="123abc456def";
123abc456def
> so $a ~~ m/ 23 && ef /
False
Run Code Online (Sandbox Code Playgroud)

它是假的,因为"$"中的"23"匹配"$"中的"23"子字符串,但此子字符串与连接中的"ef"不匹配.这有点违反直觉,因为它更容易解释$ a ~~ m/23 && ef/as"$ a匹配23和$ a匹配ef"而不是"$ a有一个匹配23的子字符串,这个子字符串也匹配ef ".

如果我有n个正则表达式并且我想看看所有这些n个正则表达式是否匹配相同的整个字符串而不是匹配整个字符串的相同子字符串部分,那么编写perl6表达式的最佳方法是什么?

在这个例子中,我真的很想做

so (($a ~~ /23/) && ($a ~~ /ef/))
Run Code Online (Sandbox Code Playgroud)

如果正则表达式的数量很大,那么除了循环外,上面的内容更难写:

so (gather {for @myRegexes { take $a ~~ / $_ /; } }).all
Run Code Online (Sandbox Code Playgroud)

有更简单的方法吗?

通过替换,它更容易阅读为"$ a匹配23或$ a匹配ef"而不是"$ a匹配23或匹配ef"的部分:

> so $a ~~ m/ 23 || ef /
True
Run Code Online (Sandbox Code Playgroud)

谢谢 !

lisprog

Jon*_*ton 10

你可以使用Junction两个正则表达式中的一个,只提$a一次.

my $a = 'abcdef12345'; say so $a ~~ /23/ & /ef/   # True
my $a = 'abcde12345'; say so $a ~~ /23/ & /ef/    # False 
my $a = 'abcdef1245'; say so $a ~~ /23/ & /ef/    # False
Run Code Online (Sandbox Code Playgroud)

要从一组正则表达式形成联结,请调用.all该数组.

如果它真的只是要查找的文字字符串,那么contains可能会运行得更快:

my $a = 'abcdef12345'; say so $a.contains(all('23', 'ef'))   # True
my $a = 'abcde12345'; say so $a.contains(all('23', 'ef'))    # False
my $a = 'abcdef1245'; say so $a.contains(all('23', 'ef'))    # False
Run Code Online (Sandbox Code Playgroud)


rai*_*iph 7

专注于简单而非速度的解决方案

暂时忽略正则表达式foo op bar and foo op baz,提供更短的通用P6构造op是纯粹的,因为并行运行多个调用是可以的foo op bar & baz.

(主语言的&运算符是一个Junction运算符.结点是具有两个关键特征的连接;一个是它们的语法简洁/简洁/清晰;另一个是它们的并行处理语义.)

将此应用于~~正则表达式匹配中的op:

my $a="123abc456def";
say so $a ~~ / 23 / & / ef /
Run Code Online (Sandbox Code Playgroud)

以上通常是合适的,只要bar & baz & ...在一条线上很好地适合.

另一种仍然使用联结逻辑但跳过操作数之间的中缀运算符的方法,并且可以更好地扩展到匹配的大型模式列表,如下所示:

my @keywords = <12 de>;
say so all ( $a.match: / $_ / for @keywords ) ;
Run Code Online (Sandbox Code Playgroud)

(感谢@lisprogtor发现并耐心地解释了我原始代码中的错误.)

专注于速度而非简单的解决方案

将有许多方法来优化速度.我只提供一个.

如果所有或大部分的模式仅仅是字符串,而不是正则表达式,然后使用.contains方法,而不是正则表达式的字符串:

say so all ( $a.contains: $_ for <23 ef> ) ;
Run Code Online (Sandbox Code Playgroud)

直观

它更容易解释$a~~m/23&&ef/为"$ a匹配23和$ a匹配ef"

是的,不是.

是的,从某种意义上讲,"匹配a和b"是不明确的; 对于任何一般探索正则表达式的人来说,你的猜测是几个合理的猜测之一; 而且,特别是,你的猜测显然是你目前认为最合适的那个,也就是"最简单".

不,如果我们的iofo匹配.

(我刚刚发明"iofo".我用它来指"在我们友好的意见"的一个版本,ioho,不仅真正谦卑,但也打算张开双臂,魔术,我/我们想象有朝一日可能意见一些读者高兴地分享.)

Iofo我们发现它更容易被读$a~~m/23&&ef/作"$ a匹配23和ef"而不是"$ a匹配23和$ a匹配ef".但当然,"$ a匹配23和ef"仍然含糊不清.

对于阅读,你建议我们有交叉点,如上所述:

say so $a ~~ / 23 / & / ef /
Run Code Online (Sandbox Code Playgroud)

就像&&在一场比赛中一样,iofo适合用英语阅读上面的"$ a匹配23和ef",但这次是"$ a匹配23和$ a匹配ef"的缩写,正如你想要的那样.

同时,&&在单个匹配中使用对应于另一个有用的连接意义,也就是说它指的是将其左侧的正则表达式原子与其右侧的正则表达式原子匹配到同一个子串.

Iofo这是一种非常直观的方法,一旦人们意识到,然后习惯了这两种可能的连接解释.