Regex 正则表达式替换在perl中是如何工作的?
我已尝试从字符串中删除重复项,Regex 正则表达式替换在perl中是如何工作的?,regex,perl,Regex,Perl,我已尝试从字符串中删除重复项,“a”、“b”、“b”、“a”、“c”,删除后的结果是“a”、“b”、“c”。我已经做到了这一点,但我对正则表达式替代的工作有怀疑 use warnings; use strict; my $s = q+"a","b","b","a","c"+; $s=~s/ ("\w"),? / ($s=~s|($1)||g)?"$1,":"" /xge; #^ ^ #| Consider this as
“a”、“b”、“b”、“a”、“c”
,删除后的结果是“a”、“b”、“c”
。我已经做到了这一点,但我对正则表达式替代的工作有怀疑
use warnings;
use strict;
my $s = q+"a","b","b","a","c"+;
$s=~s/ ("\w"),? / ($s=~s|($1)||g)?"$1,":"" /xge;
#^ ^
#| Consider this as s2
#Consider this as s1
print "\n$s\n\n";
s1
值包含字符串,如“a”、“b”、“b”、“a”、“c”
第一步
替换后:
猜猜看,以下“a”、“b”、“b”、“c”或“a”、“b”、“b”、“a”、“c”或“b”、“b”、“a”、“c”或,“b”、“b”、“c”
数据中的s1
变量是什么
我已经用eval分组运行了正则表达式
$s=~s/ ("\w"),? (?{print "$s\n"})/ ($s=~s|($1)||g)?"$1,":"" /xge;
结果是
"a","b","b","a","c"
,"b","b",,"c" #This is from after substitution
,,,,"c"
,,,,"c"
,,,,"c"
现在我的dobut是s2
变量,也是$s
为什么它没有与s1
连接,这意味着在第二步,结果应该是“a”、“b”、“b”、“c”
(所有字符串“a”
都被替换为空,并且a
被添加到$s
)
已编辑
eval分组的结果是(?{print$s})
在替换行之后,我打印了$s
变量,它给出了“a”、“b”、“c”
,这个输出是如何产生的。在我看来,正则表达式是这里使用的错误工具。我会的
split
逗号上的字符串
- 从剥离返回的列表中删除重复项
将列表重新连接成字符串
像这样:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $str = q["a","b","b","a","c"];
my %seen;
$str = join ',',
grep { ! $seen{$_}++ }
split /,/, $str;
say $str;
在我看来,正则表达式是这里使用的错误工具。我会的
split
逗号上的字符串
- 从剥离返回的列表中删除重复项
将列表重新连接成字符串
像这样:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $str = q["a","b","b","a","c"];
my %seen;
$str = join ',',
grep { ! $seen{$_}++ }
split /,/, $str;
say $str;
正如@Dave Cross已经演示的那样,正确的解决方案是拆分、过滤和重新加入
然而,下面的正则表达式解决方案确实有效,并有望证明Dave的解决方案的优越性
#!/usr/bin/env perl
use v5.10;
use strict;
use warnings;
my $str = q{"a","b","b","a","c"};
1 while $str =~ s{
\A
(?: (?&element) , )*
( (?&element) ) # Capture in \1
(?: , (?&element) )*
\K
,
\1 # Remove the duplicate along with preceding comma
(?= \z | , )
(?(DEFINE)
(?<element>
"
\w
"
)
)
}{}xg;
say $str;
正如@Dave Cross已经演示的那样,正确的解决方案是拆分、过滤和重新加入
然而,下面的正则表达式解决方案确实有效,并有望证明Dave的解决方案的优越性
#!/usr/bin/env perl
use v5.10;
use strict;
use warnings;
my $str = q{"a","b","b","a","c"};
1 while $str =~ s{
\A
(?: (?&element) , )*
( (?&element) ) # Capture in \1
(?: , (?&element) )*
\K
,
\1 # Remove the duplicate along with preceding comma
(?= \z | , )
(?(DEFINE)
(?<element>
"
\w
"
)
)
}{}xg;
say $str;
检查正则表达式并推断它应该做什么是相当困难的,可能将其拆分为多行并为每个块添加注释,也许其他人会努力投入一些时间来解决您的问题。在我看来,您的问题来自正则表达式中的空格。如果您尝试$s=~s/(“\w”)/_/G打印“\n将\$1替换为\$s后重试”
,您会注意到字符串没有更改,但是如果删除空格,您将得到$s=~s/(“\w”),?/\ug
然后,$1
将被\uU
替代。我认为re
模块中有用于调试的模块。有趣的是,使用e
标志揭示s
命令的精确语义,但该代码不可读,我会将其丢弃,以支持更可读的方法。同样的事情也适用于$s ~
的初始化:这很难理解,所以最好使用一个大家都知道的表单。检查正则表达式并推断它应该做什么非常困难,也许将其拆分为多行,并为每个块添加注释,也许其他人会努力投入一些时间来解决您的问题。在我看来,您的问题来自正则表达式中的空格。如果您尝试$s=~s/(“\w”)/_/G打印“\n将\$1替换为\$s后重试”
,您会注意到字符串没有更改,但是如果删除空格,您将得到$s=~s/(“\w”),?/\ug
然后,$1
将被\uU
替代。我认为re
模块中有用于调试的模块。有趣的是,使用e
标志揭示s
命令的精确语义,但该代码不可读,我会将其丢弃,以支持更可读的方法。同样的事情也适用于$s ~
的初始化:这很难理解,所以最好使用一个大家都清楚的表单。谢谢你的回答。在使用正则表达式之前,我尝试过使用散列,但结果是,数据被洗牌,所以我转向正则表达式。现在你的答案解决了我的散列洗牌问题。但是我很想知道正则表达式替换是如何工作的。谢谢你的回答。在使用正则表达式之前,我尝试过使用散列,但结果是,数据被洗牌,所以我转向正则表达式。现在你的答案解决了我的散列洗牌问题。但我很想知道正则表达式替换是如何工作的。