我有一个名单列表,我想查找包含两个使用变量签名的给定字母的名称。
$one = "A";
$two = "O";
请注意,我希望这些字母出现在已检查的名称中的任何位置,以便我可以得到这样的输出:
Jason
Damon
Amo
Noma
Boam
...
但每个字母每个字母只能出现一次,这意味着这不起作用。
Alamo
我已尝试过这段代码,但它不起作用。
foreach my $name (@list) {
if ($name =~ /$one/) {
if ($name =~ /$two/) {
print $name;
}}
else {next}; }
答案 0 :(得分:3)
这个怎么样?
for my $name (@list) {
my $ones = () = $name =~ /$one/gi;
my $twos = () = $name =~ /$two/gi;
if ($ones == 1 && $twos == 1) {
print $name;
}
}
答案 1 :(得分:0)
将它全部放入单个正则表达式的一种方法是使用正则表达式模式中的表达式,根据首先找到的字母来搜索另一个字母(a或o):
#!/usr/bin/env perl
use 5.010; use strict; use warnings;
while(<DATA>){
chomp;
say if m/^
[^ao]* # anything but a or o
([ao]) # an 'a' or 'o'
[^ao]* # anything but a or o
(??{($1 and lc($1) eq 'a') ? 'o' : 'a'}) # the other 'a' or 'o'
[^ao]* $/xi; # anything but a or o
}
__DATA__
Abdi
Chelal
Jucal
Husham
Gallio
Pileser
Tekoa
Kenaz
Raphah
有关详细信息,请参阅扩展表达式的perlre部分。
答案 2 :(得分:-1)
可以坚持使用正则表达式 可能会出现正则表达式的表现力 超过分裂和其他黑客方法。
让正则表达式为你完成所有工作 Formatted:
^
(?= .* a ) # Must be one of 'a'
(?= .* o ) # Must be one of 'o'
(?!
(?: .* a ){2} # Cannot be 2 of 'a'
)
(?!
(?: .* o ){2} # Cannot be 2 of 'o'
)
.+
$
Perl
use strict;
use warnings;
my $one = "A";
my $two = "O";
my $rx = qr/^(?=.*$one)(?=.*$two)(?!(?:.*$one){2})(?!(?:.*$two){2}).+$/i;
my @list = qw{
Damon
Amo
Noma
Boam
Alamo
};
my @found = grep{ /$rx/ } @list;
print "@found";
输出:
Damon Amo Noma Boam
答案 3 :(得分:-1)
这是我的解决方案。你不清楚是否总会有两个单字符串匹配,但我认为可能有更多
不幸的是,计算字符出现次数的经典方法 - tr///
- 不会将变量插入到搜索列表中,并且没有与案例无关的修饰符{{1 }}。但模式匹配运算符/i
确实如此,这就是我使用的
我完全不喜欢所谓的 goatse 运算符,但是我知道没有更简洁的方法可以让你计算全局正则表达式匹配的次数
我本可以使用m//
作为内循环,但是我选择了常规的grep
循环和带有标签的for
,因为我相信它更具可读性{ p>
next
use strict;
use warnings;
use v5.10.1;
use autodie;
my @list = do {
open my $fh, '<', 'names.txt';
<$fh>;
};
chomp @list;
my ($one, $two) = qw/ A O /;
NAME:
for my $name ( @list ) {
for ( $one, $two) {
my $count = () = $name =~ /$_/gi;
next NAME unless $count == 1;
}
say $name;
}
Gallio
Tekoa
Achbor
Clopas