….
my $sequence = 'AACAAATTGAAACAATAAACAGAAACAAAAATGGATGCGATCAAGAAAAAGATGC'. 'AGGCGATGAAAATCGAGAAGGATAACGCTCTCGATCGAGCCGATGCCGCGGAAGA'. 'AAAAGTACGTCAAATGACGGAAAAGTTGGAACGAATCGAGGAAGAACTACGTGAT'. 'ACCCAGAAAAAGATGATGCNAACTGAAAATGATTTAGATAAAGCACAGGAAGATT'. 'TATCTGTTGCAAATACCAACTTGGAAGATAAGGAAAAGAAAGTTCAAGAGGCGGA'. 'GGCTGAGGTAGCANCCCTGAATCGTCGTATGACACTTCTGGAAGAGGAATTGGAA'. 'CGAGCTGAGGAACGTTTGAAGATTGCAACGGATAAATTGGAAGAAGCAACACATA'. 'CAGCTGATGAATCTGAACGTGTTCGCNAGGTTATGGAAA';my $string = <STDIN>;chomp $string;while ($sequence =~ /$string/gi ){ printf "Sequence found at position: %d\n",pos($sequence)- length($string);}
这是我的foreach方法:
foreach ($sequence =~ /$string/gi ) printf "Sequence found at position: %d\n",pos($sequence) - length($string); }
有人可以告诉我为什么它不能以同样的方式工作吗?
谢谢!
如果我输入“aaca”,我的输出:
Part 1 using a while loopSequence found at position: 0Sequence found at position: 10Sequence found at position: 17Sequence found at position: 23Sequence found at position: 377Part 2 using a foreach loopSequence found at position: -4Sequence found at position: -4Sequence found at position: -4Sequence found at position: -4Sequence found at position: -4解决方法 你的问题是上下文.在while循环中,条件位于标量上下文中.在标量上下文中,g模式下的匹配运算符将沿着字符串顺序匹配.因此,在循环中检查pos可以满足您的需求.
在foreach循环中,条件位于列表上下文中.在列表上下文中,g模式下的匹配运算符将返回所有匹配的列表(并且它将在输入循环体之前计算所有匹配). foreach然后逐个将匹配加载到$_中,但是你永远不会使用变量.循环体中的pos没有用,因为它包含匹配结束后的结果.
这里要说的是,如果你想要pos工作,并且你正在使用g修饰符,你应该使用while循环来强制标量上下文并使正则表达式遍历字符串中的匹配.
思南启发我写了几个foreach例子:
>使用拆分分隔符保留模式时,这个是相当简洁的:
my $pos = 0;foreach (split /($string)/i => $sequence) { print "Sequence found at position: $pos\n" if lc eq lc $string; $pos += length;}
>正则表达式相当于拆分解决方案:
my $pos = 0;foreach ($sequence =~ /(\Q$string\E|(?:(?!\Q$string\E).)+)/gi) { print "Sequence found at position: $pos\n" if lc eq lc $string; $pos += length;}
>但这显然是解决您问题的最佳方案:
{package Dumb::Homework; sub TIEARRAY { bless { haystack => $_[1],needle => $_[2],size => 2**31-1,pos => [],} } sub FETCH { my ($self,$index) = @_; my ($pos,$needle) = @$self{qw(pos needle)}; return $$pos[$index] if $index < @$pos; while ($index + 1 >= @$pos) { unless ($$self{haystack} =~ /\Q$needle/gi) { $$self{size} = @$pos; last } push @$pos,pos ($$self{haystack}) - length $needle; } $$pos[$index] } sub FETCHSIZE {$_[0]{size}}}tIE my @pos,'Dumb::Homework' => $sequence,$string;print "Sequence found at position: $_\n" foreach @pos; # look how clean it is
它最好的原因是因为其他两个解决方案必须首先处理整个全局匹配,然后才能看到结果.对于可能有问题的大输入(如DNA). Dumb :: Homework包实现了一个数组,每次foreach迭代器请求它时都会懒洋洋地找到下一个位置.它甚至会存储位置,以便您可以再次访问它们而无需重新处理. (事实上,它看起来超过了请求的匹配,这使得它可以在foreach中正确结束,但仍然比处理整个列表要好得多)>实际上,最好的解决方案仍然是不使用foreach,因为它不是正确的工具.
总结以上是内存溢出为你收集整理的在Perl中,如果强制使用foreach循环,如何在字符串中找到匹配的位置? POS全部内容,希望文章能够帮你解决在Perl中,如果强制使用foreach循环,如何在字符串中找到匹配的位置? POS所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)