Я написал код ниже, чтобы обмануть Wordle (я не очень хорош в этом). Есть ли способ объединить следующую часть в один оператор регулярного выражения:
($word =~ m/c/i) and
($word =~ m/a/i) and
($word =~ m/o/i)
То есть найти слова, содержащие все три буквы «с», «а», «о», в любом порядке.
#!/usr/bin/perl
use 5.30.3;
use warnings;
my $dic_file = "/usr/share/dict/web2";
open (IN,"<", $dic_file) or die "Cannot open file.\n $!";
while (my $word=<IN>){
chomp $word;
if (length($word) == 5){
if ( ($word !~ m/[rtn]/i) and
($word =~ m/c/i) and
($word =~ m/a/i) and
($word =~ m/o/i)
){
say $word;
}
}
}
В таких случаях может пригодиться функция match_all($word, qr//, qr//,..) .





Вы можете добиться больших успехов, используя $_ вместо $word.
my $dic_file = "/usr/share/dict/web2";
open( my $fh, "<", $dic_file )
or die( "Can't open `$dic_file`: $!\n" );
while ( <$fh> ) {
chomp;
say if length == 5 && !/[rtn]/i && /c/i && /a/i && /o/i;
}
Можно получить «и» из регулярного выражения, используя просмотр вперед.
my $dic_file = "/usr/share/dict/web2";
open( my $fh, "<", $dic_file )
or die( "Can't open `$dic_file`: $!\n" );
while ( <$fh> ) {
chomp;
say if /^(?=.*c)(?=.*a)(?=.*o)[^rtn]{5}\z/si;
}
Вы можете легко написать это как однострочник.
perl -nle'print if /^(?=.*c)(?=.*a)(?=.*o)[^rtn]{5}\z/si' /usr/share/dict/web2
совет: в общем, вы должны использовать
&&, а неand. Приоритет последнего немного удивителен, если вы к нему не привыкли, и вы почти всегда хотите приоритет первого.