use*_*370 7 regex perl replace raku
我的文本输入类似于以下所示。我想auto在每个“ a = b”模式之前添加单词,但前提是该单词是关键字后面的序列的一部分kywrd(由分号分隔)。
kywrd a=b;c=d;
e=f;
fnctn z;
g=h;
Run Code Online (Sandbox Code Playgroud)
所以我在这里寻找的输出是:
kywrd2 auto a=b;auto c=d;
auto e=f;
fnctn z;
g=h;
Run Code Online (Sandbox Code Playgroud)
下面的Perl6(Raku?)代码使用正则表达式添加auto关键字,但仅在第一个 a=b模式之前添加。有没有一种简单的方法可以执行序列中所有模式的替换;保持g=h;不变?
kywrd a=b;c=d;
e=f;
fnctn z;
g=h;
Run Code Online (Sandbox Code Playgroud)
One possible way that keeps the regexing to a minimum:
sub repl ($input)
{
$input.Str
.split(';', :skip-empty)
.map( 'auto ' ~ * ~ ';')
.join('')
};
my $foo = 'kywrd a=b;c=d;d=e;';
$foo ~~ s:g /kywrd \s+ (.+)/kywrds2 { repl($0) }/;
$foo.say;
Run Code Online (Sandbox Code Playgroud)
Personally I'd prefer the method form subst over the s// operator though.
$foo .= subst(/ kywrd \s+ (.+) /, "kywrds2 { repl($0) }", :g);
Run Code Online (Sandbox Code Playgroud)
单程:
# Create a separate named regex that captures an `x=y;` pair:
my regex pair { (\w+) \= (\w+) \; (\s*) }
# (Capture `(\s*)` so formatting between pairs is retained)
# Generate and return 'auto'-ized replacement of a captured pair:
sub auto-ize ($/) { "auto $0=$1;$2" }
$x ~~ s:g { kywrd \s+ <pair>+ } = "kywrd2 $<pair>».&auto-ize.join()";
Run Code Online (Sandbox Code Playgroud)
对于稍微熟悉Raku的人来说,我展示的所有代码都很容易理解,但是我还是会解释一下。
我已经分解出一个命名的正则表达式来匹配一对。(有关为什么/如何调用正则表达式的详细信息,请参见我对Perl 6 / Raku中捕获和不捕获正则表达式范围差异的回答。)<pair>pair
所述auto-ize子例程使用的匹配变量($/)作为其参数。这很方便,因为$0等会自动别名给与传递的匹配对象关联的编号捕获。
我使用了该格式的语法,s [ ... ] = " ... "因为我认为这种用例更易读。(请参阅s///文档中有关“不同定界符”的提及。)
“ kywrd2 ...”字符串将被重复评估,并成为多个s:g匹配项中每个匹配项的一次替换。
该$<pair>».&auto-ize.join()位是根据双引号字符串规则内插的代码。
$<pair>是的缩写$/<pair>,即的<pair>关键$/。它是指pair与match变量关联的命名捕获。后者将s:g依次对应于多个匹配项中的每个匹配项。
+regex表达式中的量词<pair>+表示,如果匹配,它将产生一个List捕获(匹配)对象,而不是一个对象(就像表达式是just <pair>或的情况一样<pair>?)。
»将其LHS操作数视为树或列表(在这种情况下为一个或多个捕获/匹配对象的列表,每foo=bar;...对一个),并遍历其元素。对于每个“叶”元素,»都在其右侧执行操作。(它»是一个功能强大的运算符,但具有很好的简单用例,例如在这种情况下,它在概念上仅是方便且紧凑的for循环等效项。您可以编写它,>>就像使用ASCII一样。)
.&auto-ize调用auto-ize子例程,就好像它是一个方法一样,使用其左侧的操作数作为第一个参数。
来自@PolarBear答案的测试输入数据:
kywrd a=b;c=d;
e=f;
fnctn z;
g=h;
k=m;
fnctn y;
kywrd m=n;
k=j;
kywrd z=a;b=i;
kywrd c=x;e=i;
z=q;
fnctn o;
Run Code Online (Sandbox Code Playgroud)
将其放入in.q并显示say结果out.q显示:
kywrd2 auto a=b;auto c=d;
auto e=f;
fnctn z;
g=h;
k=m;
fnctn y;
kywrd2 auto m=n;
auto k=j;
kywrd2 auto z=a;auto b=i;
kywrd2 auto c=x;auto e=i;
auto z=q;
fnctn o;
Run Code Online (Sandbox Code Playgroud)