彩色匹配,有些正则表达式插值有效,有些则无效;颜色代码不一致

问题描述 投票:0回答:3

我有一些长行,我想用我想要的颜色突出显示匹配项。一个函数使用替换,另一个函数使用递归。有些有效,有些则无效;我正在寻找一种一致的方法来插入正则表达式。

sub colorMatch ($aStr, $aRegex, $aColor) {
    my $colorOff = '\e[0m';
    my $a =$aStr.subst(/(<{$aRegex}>)/, $aColor ~ "# $/ #" ~ $colorOff, :g);
    # not working, $/ not interpolating corresponding matches, all Nil
    say $a;
}

colorMatch("a-12-b-3-c-4-def-567", '\d+', '\e[1;31m');
colorMatch("a-12-b-3-c-4-def-567", '<alpha>+', '\e[1;31m');
say "\e[1;31m" ~ " color1 " ~ "\e[0m" ~ 
    "\e[1;36m" ~ " color2 " ~ "\e[0m";

sub colorMatch2 ($aStr, $aRegex, $colorNumber) {
    my $colorOff = "\e[0m";
    if $aStr.chars > 0 {
    my $x1 = ($aStr ~~ m/<{$aRegex}>/);
    my $x2 = $x1.prematch;
    my $x3 = $x1.Str;
    my $x4 = $x1.postmatch;
    return ($x2 ~ "\e[1;{$colorNumber}m" ~ $x3 ~ $colorOff)
        ~ colorMatch2($x4, $aRegex, $colorNumber);
    }
}

say colorMatch2("a-12-b-3-c-4-def-567", '\d+', 31); # works, red color
say colorMatch2("a-12-b-3-c-4-def-567", '567', 36); # works, green color
say colorMatch2("a-12-b-3-c-4-def-567", '\w+', 31); # works, red color
say colorMatch2("a-12-b-3-c-4-def-567", '[a..z]+', 31); # fails with [] and ..
say colorMatch2("a-12-b-3-c-4-def-567", "<alpha>+", 31); # fails with <>


Use of Nil in string context
  in sub colorMatch at colorMatch.pl line 4
a-\e[1;31m#  #\e[0m-b-\e[1;31m#  #\e[0m-c-\e[1;31m#  #\e[0m-def-\e[1;31m#  #\e[0m

# seems to do substitution, but $/ is empty and color not shown;

Use of Nil in string context
  in sub colorMatch at colorMatch.pl line 4
\e[1;31m#  #\e[0m-12-\e[1;31m#  #\e[0m-3-\e[1;31m#  #\e[0m-4-\e[1;31m#  #\e[0m-567

# seems to do substitution, but $/ is empty and color not shown;

 color1  color2 # both colors work and shown as expected, 
 # color1 red and color 2 green; why inconsistent with above???

a-12-b-3-c-4-def-567 # works, red color
a-12-b-3-c-4-def-567 # works, green color
a-12-b-3-c-4-def-567 # works, red color
No such method 'prematch' for invocant of type 'Bool'
  in sub colorMatch2 at colorMatch.pl line 17
  in block <unit> at colorMatch.pl line 28
regex colors match interpolation raku
3个回答
4
投票

这不是插值问题。字符类和范围的语法略有不同。你需要:

'text' ~~ / <[a..z]>+ /

至于在布尔值上调用

prematch()
的其他错误,结果是
False
因为在最终的递归级别中,它不再匹配。在假设匹配之前,您需要检查结果。

最后,对于“在字符串上下文中使用 Nil”,这是因为您使用的是

Str.subst
,并且像大多数语言中的大多数函数调用一样,参数在函数开始之前进行评估。您在参数中使用了
$/
,但它尚未设置,因为函数体甚至还没有开始执行。
s/match/replacement/
操作符不会遇到这个困难,所以我建议你将代码更改为:

$aStr ~~ s:g/(<$aRegex>)/$aColor# $/ #$colorOff/;

(或者为了更好的可读性:)

$aStr ~~ s:g {(<$aRegex>)} = "$aColor# $/ #$colorOff";

这假设您已将

$aRegex
制作为正则表达式而不是字符串。另外,由于新代码修改了
$aStr
,因此需要将函数签名中的
$aStr
更改为
$aStr is copy


2
投票

谢谢大家的帮助。这是我的修改版本。唯一的问题是,由于某种原因我无法弄清楚,替换函数不解释颜色代码,但相同的颜色代码适用于简单的“say”例程。谢谢!

注意:定义 'my $x = rx/$aRegex/' 然后使用 '/< $x >/' 的效果是不可预测的;所以我最终使用/<{$aRegex}>/;

sub colorMatch ($aStr, $aRegex, $aColor) {
    my $colorOff = '\e[0m';
    my $x = rx/$aRegex/;
    my $bStr = $aStr;
    $_ = $aStr;
    # my $a =$aStr.subst(/(<$x>)/, $aColor ~ "# $/ #" ~ $colorOff, :g);
    # $bStr ~~ s:g/(<$x>)/$aColor ~ "# $/ #" ~ $colorOff/;
    # s:g/(<{$aRegex}>)/($aColor $/ $colorOff)/;
    s:g/(<{$aRegex}>)/($aColor $/ $colorOff)/;
    say $_; # for some reason, color codes are not interpreted;
}

colorMatch("a-12-b-3-c-4-def-567", '\d+', '\e[1;31m');
colorMatch("a-12-b-3-c-4-def-567", '<alpha>+', '\e[1;36m');
say "\e[1;31m" ~ " color1 " ~ "\e[0m" ~ "\e[1;36m" ~ " color2 " ~ "\e[0m";
say "a-\e[1;31m 12 \e[0m-b-\e[1;31m 3 \e[0m-c-\e[1;31m 4 \e[0m-def-\e[1;31m 567 \e[0m"; # this works; 
say "\e[1;31m a \e[0m-12-\e[1;31m b \e[0m-3-\e[1;31m c \e[0m-4-\e[1;31m def \e[0m-567"; # this works
say "(\e[1;36m a \e[0m)-12-(\e[1;36m b \e[0m)-3-(\e[1;36m c \e[0m)-4-(\e[1;36m def \e[0m)-567"; # works

sub colorMatch2 ($aStr, $aRegex, $colorNumber) {
    my $colorOff = "\e[0m";
    # my $x = rx/$aRegex/;
    # say $x; # /$x/ or /<$x>/ do not all work; prints out "rx/$aRegex/"
    if $aStr.chars > 0 {
    my $x1 = ($aStr ~~ m/<{$aRegex}>/); # <{$aRegex}> works
    my $x2 = $x1 ?? $x1.prematch !! $aStr;
    my $x3 = $x1 ?? $x1.Str !! "";
    my $x4 = $x1 ?? $x1.postmatch !! "";
    return ($x2 ~ "\e[1;{$colorNumber}m" ~ $x3 ~ $colorOff)
        ~ colorMatch2($x4, $aRegex, $colorNumber);
    } else {
    return "";
    }
}

# colorMatch2 all works now:

say colorMatch2("a-12-b-3-c-4-def-567", '\d+', 31);
say colorMatch2("a-12-b-3-c-4-def-567", '567', 36);
say colorMatch2("a-12-b-3-c-4-def-567", '\w+', 31);
say colorMatch2("a-12-b-3-c-4-def-567", '<[a..z]>+', 31);
say colorMatch2("a-12-b-3-c-4-def-567", "<alpha>+", 31);

结果:

a-(\e[1;31m 12 \e[0m)-b-(\e[1;31m 3 \e[0m)-c-(\e[1;31m 4 \e[0m)-def-(\e[1;31m 567 \e[0m)
(\e[1;36m a \e[0m)-12-(\e[1;36m b \e[0m)-3-(\e[1;36m c \e[0m)-4-(\e[1;36m def \e[0m)-567
 color1  color2 
a- 12 -b- 3 -c- 4 -def- 567 
a -12- b -3- c -4- def -567
( a )-12-( b )-3-( c )-4-( def )-567
a-12-b-3-c-4-def-567
a-12-b-3-c-4-def-567
a-12-b-3-c-4-def-567
a-12-b-3-c-4-def-567
a-12-b-3-c-4-def-567

1
投票

您可能还想查看 Terminal::ANSIColor

https://github.com/tadzik/Terminal-ANSIColor/

我怀疑你的代码作为语法和动作也能很好地工作,并且更具可读性。因为您本质上是想在一段文本上运行一组正则表达式。 https://docs.perl6.org/language/grammar_tutorial

© www.soinside.com 2019 - 2024. All rights reserved.