我理解如何以下列方式在Perl中使用正则表达式:
$str =~ s/expression/replacement/g;
据我所知,如果表达式的任何部分括在括号中,可以在替换部分中使用和捕获它,如下所示:
$str =~ s/(a)/($1)dosomething/;
但是有没有办法捕获正则表达式之外的以上的($1)
?
我有一个完整的单词,这是一串辅音,例如bEdmA
,其元音化版本baEodamaA
(其中a
和o
为元音),以及由空格分隔的两个标记的分割形式bEd maA
。我想从完整的单词中选择标记的元音形式,如:beEoda
,maA
。我试图在完整的单词表达式中捕获令牌,所以我有:
$unvowelizedword = "bEdmA";
$tokens[0] = "bEd", $tokens[1] = "mA";
$vowelizedword = "baEodamA";
foreach $t(@tokens) {
#find the token within the full word, and capture its vowels
}
我正在尝试做这样的事情:
$vowelizedword = m/($t)/;
这是完全错误的,原因有两个:令牌$t
不是以自己的形式出现,例如bEd
,但m/b.E.d/
之类的内容会更相关。另外,如何在变量外部正则表达式中捕获它?
真正的问题是:如果来自完整单词baEoda
的标记maA
,bEd
,我如何捕获元音序列mA
和beEodamaA
?
我从所有答案中意识到我错过了两个重要细节。
我只提到了两个元音,但还有更多,包括由两个字符组成的符号,如'~a'。完整列表(虽然我认为我不需要在这里提及)是:
@vowels =('a','我','你','o','〜','〜一','〜我','〜你','N','F', 'K','~N','〜K');
答案 0 :(得分:1)
以下似乎可以做你想做的事:
#!/usr/bin/env perl
use warnings;
use strict;
my @tokens = ('bEd', 'mA');
my $vowelizedword = "beEodamaA";
my @regex = map { join('.?', split //) . '.?' } @tokens;
my $regex = join('|', @regex);
$regex = qr/($regex)/;
while (my ($matched) = $vowelizedword =~ $regex) {
$vowelizedword =~ s{$regex}{};
print "matched $matched\n";
}
根据您更新的问题进行更新(元音是可选的)。它从字符串的末尾开始工作,因此您必须将令牌收集到一个数组中并反向打印它们:
#!/usr/bin/env perl
use warnings;
use strict;
my @tokens = ('bEd', 'mA', 'Al', 'ywm');
my $vowelizedword = "beEodamaA Alyawmi"; # Caveat: Without the space it won't work.
my @regex = map { join('.?', split //) . '.?$' } @tokens;
my $regex = join('|', @regex);
$regex = qr/($regex)/;
while (my ($matched) = $vowelizedword =~ $regex) {
$vowelizedword =~ s{$regex}{};
print "matched $matched\n";
}
答案 1 :(得分:0)
在所谓的“列表上下文”中使用m//
运算符,如下所示:
my @tokens = ($input =~ m/capturing_regex_here/modifiershere);
答案 2 :(得分:0)
ETA:根据我现在的理解,您要说的是您希望在令牌的每个字符后匹配可选的元音。
有了这个,您可以调整$vowels
变量以仅包含您寻找的字母。或者,您也可以使用.
来捕获任何角色。
use strict;
use warnings;
use Data::Dumper;
my @tokens = ("bEd", "mA");
my $full = "baEodamA";
my $vowels = "[aeiouy]";
my @matches;
for my $rx (@tokens) {
$rx =~ s/.\K/$vowels?/g;
if ($full =~ /$rx/) {
push @matches, $full =~ /$rx/g;
}
}
print Dumper \@matches;
<强>输出:强>
$VAR1 = [
'baEoda',
'mA'
];
请注意
... $full =~ /$rx/g;
在正则表达式中not require capturing groups。
答案 3 :(得分:0)
我怀疑有一种更简单的方法可以做任何你想要完成的事情。诀窍不是让正则表达式代码变得如此棘手,以至于你忘记了它实际上在做什么。
我只能开始猜测你的任务,但从你的单个例子看,你好像要检查两个子字符是否在更大的标记中,忽略了某些字符。我猜这些子标记必须是有序的,除了那些元音字符之外,它们之间不能有任何其他东西。
为了匹配标记,我可以在标量上下文中使用带有\G
全局标志的/g
锚点。这会将匹配锚定到同一标量的最后一个匹配结束后的字符1。这种方式允许我为每个子令牌分别设置模式。这更容易管理,因为我只需要更改@subtokens
中的值列表。
一旦你完成每一对并找到哪些匹配所有模式,我就可以从该对中提取原始字符串。
use v5.14;
my $vowels = '[ao]*';
my @subtokens = qw(bEd mA);
# prepare the subtoken regular expressions
my @patterns = map {
my $s = join "$vowels", map quotemeta, (split( // ), '');
qr/$s/;
} @subtokens;
my @tokens = qw( baEodamA mAabaEod baEoda mAbaEoda );
my @grand_matches;
TOKEN: foreach my $token ( @tokens ) {
say "-------\nMatching $token..........";
my @matches;
PATTERN: foreach my $pattern ( @patterns ) {
say "Position is ", pos($token) // 0;
# scalar context /g and \G
next TOKEN unless $token =~ /\G($pattern)/g;
push @matches, $1;
say "Matched with $pattern";
}
push @grand_matches, [ $token, \@matches ];
}
# Now report the original
foreach my $tuple ( @grand_matches ) {
say "$tuple->[0] has both fragments: @{$tuple->[1]}";
}
现在,这是关于这个结构的好处。我可能猜错了你的任务。如果有,可以轻松修复而无需更改设置。假设子记录不必按顺序排列。这对我创建的模式很容易改变。我只是摆脱了
\G
锚点和/g
标志;
next TOKEN unless $token =~ /($pattern)/;
或者,假设令牌必须是有序的,但其他东西可能在它们之间。我可以插入.*?
来匹配这些东西,有效地跳过它:
next TOKEN unless $token =~ /\G.*?($pattern)/g;
如果我可以从创建模式的map
管理所有这些内容会更好,但/g
标志不是模式标志。它必须与运营商合作。
当我没有将所有内容都包装在一个正则表达式中时,我发现管理不断变化的需求要容易得多。
答案 4 :(得分:-1)
假设令牌需要按顺序出现,并且它们之间没有任何东西(除了元音之外):
my @tokens = ( "bEd", "mA" );
my $vowelizedword = "baEodamaA";
my $vowels = '[ao]';
my (@vowelized_sequences) = $vowelizedword =~ ( '^' . join( '', map "(" . join( $vowels, split( //, $_ ) ) . "(?:$vowels)?)", @tokens ) . '\\z' );
print for @vowelized_sequences;