Regex 正则表达式,Perl中使用字符串变量的匹配运算符
我正在使用一个Regex 正则表达式,Perl中使用字符串变量的匹配运算符,regex,perl,string-matching,Regex,Perl,String Matching,我正在使用一个regex,但是得到了一些奇怪的、意想不到的“匹配”。“名称”被发送到子例程,以便与名为@ASlist的数组进行比较,该数组包含多行。每行的第一个元素也是一个名称,后跟0到几个同义词。目标是将传入的“名称”匹配到@ASlist中具有匹配单元格的任何行 示例输入,从中导出$names,用于与@ASlist进行比较: 13 1 13 chr7 7 70606019 74345818 Otud7a Klf13 E030018B13Rik Trpm1
regex
,但是得到了一些奇怪的、意想不到的“匹配”。“名称”被发送到子例程,以便与名为@ASlist
的数组进行比较,该数组包含多行。每行的第一个元素也是一个名称,后跟0到几个同义词。目标是将传入的“名称”匹配到@ASlist
中具有匹配单元格的任何行
示例输入,从中导出$names
,用于与@ASlist
进行比较:
13 1 13 chr7 7 70606019 74345818 Otud7a Klf13 E030018B13Rik Trpm1 Mir211 Mtmr10 Fan1 Mphosph10 Mcee Apba2 Fam189a1 Ndnl2 Tjp1 Tarsl2 Tm2d3 1810008I18Rik Pcsk6 Snrpa1 H47 Chsy1 Lrrk1 Aldh1a3 Asb7 Lins Lass3 Adamts17
@ASlist中的样本行:
HSPA5 BIP FLJ26106 GRP78 MIF2
NDUFA5 B13 CI-13KD-B DKFZp781K1356 FLJ12147 NUFM UQOR13
ACAN AGC1 AGCAN CSPG1 CSPGCP MSK16 SEDK
守则:
my ($name) = @_; ## this comes in from another loop elsewhere in code I did not include
chomp $name;
my @collectmatches = (); ## container to collect matches
foreach my $ASline ( @ASlist ){
my @synonyms = split("\t", $ASline );
for ( my $i = 0; $i < scalar @synonyms; $i++ ){
chomp $synonyms[ $i ];
#print "COMPARE $name TO $synonyms[ $i ]\n";
if ( $name =~m/$synonyms[$i]/ ){
print "\tname $name from block matches\n\t$synonyms[0]\n\tvia $synonyms[$i] from AS list\n";
push ( @collectmatches, $synonyms[0], $synonyms[$i] );
}
else {
# print "$name does not match $synonyms[$i]\n";
}
}
}
my($name)=@;##这来自我没有包含的代码中其他地方的另一个循环
chomp$name;
我的@collectmatches=();##收集火柴的容器
foreach my$ASline(@ASlist){
my@synonyms=split(“\t”,$ASline);
对于(my$i=0;$i
脚本正在运行,但也报告了奇怪的匹配。例如,当$name
为“E030018B13Rik”时,它与出现在@ASlist
中的“NDUFA5”匹配。这两者不应该匹配
如果我将正则表达式从
~m/$synonyms[$I]/
更改为~m/^$synonyms[$I]$/
,则“奇怪的”匹配将消失,但脚本将错过绝大多数匹配。NDUFA5
记录包含B13
作为模式,它将匹配E030018Rik
如果希望更具文字性,请将边界条件添加到正则表达式/\b…。\b/
。还应该使用转义正则表达式特殊字符
或者,如果您想测试直接相等,那么只需使用
您正在使用
B13
作为正则表达式。由于所有字符都没有特殊含义,因此包含子字符串B13
的任何字符串都与表达式匹配
E030018B13Rik
^^^
如果希望表达式与整个字符串匹配,请使用锚定:
if ($name =~m/^$synonyms[$i]$/) {
或者,使用
index
或eq
检测子字符串(或分别检测相同的字符串),因为您的输入似乎没有使用正则表达式的任何功能。因为您只需要比较两个字符串,您可以简单地使用eq:
if ( $name eq $synonyms[$i] ){
另一种更完善的测试字符串相等性的方法是使用散列 您没有显示任何真实的测试数据,但是这个简短的Perl程序从匹配字符串行的数组
@ASlist
构建了一个哈希。之后,大部分工作都完成了
随后的for
循环只测试E030018B13Rik
,查看它是否是新%ASlist
的键之一,并打印适当的消息
use strict;
use warnings;
my @ASlist = (
'HSPA5 BIP FLJ26106 GRP78 MIF2',
'NDUFA5 B13 CI-13KD-B DKFZp781K1356 FLJ12147 NUFM UQOR13',
'ACAN AGC1 AGCAN CSPG1 CSPGCP MSK16 SEDK',
);
my %ASlist = map { $_ => 1 } map /\S+/g, @ASlist;
for (qw/ E030018B13Rik /) {
printf "%s %s\n", $_, $ASlist{$_} ? 'matches' : 'doesn\'t match';
}
输出
E030018B13Rik doesn't match
我不明白,这两者到底是如何匹配的?因为
B13
在字符串e30018b13rik
中。如果你不想让它像那样运行,你需要给正则表达式添加边界条件。我用这些精确的锚丢失了许多可能的匹配,但我发现我可以修改正则表达式使其不区分大小写…你的输入数据看起来像固定宽度的数据。是这样吗?如果是这样,正则表达式甚至可能不是解包数据的最佳工具。
use strict;
use warnings;
my @ASlist = (
'HSPA5 BIP FLJ26106 GRP78 MIF2',
'NDUFA5 B13 CI-13KD-B DKFZp781K1356 FLJ12147 NUFM UQOR13',
'ACAN AGC1 AGCAN CSPG1 CSPGCP MSK16 SEDK',
);
my %ASlist = map { $_ => 1 } map /\S+/g, @ASlist;
for (qw/ E030018B13Rik /) {
printf "%s %s\n", $_, $ASlist{$_} ? 'matches' : 'doesn\'t match';
}
E030018B13Rik doesn't match