Perl正则如何正确匹配句子中所有连续相邻单词对
问题原因
你当前代码拿不到全量相邻词对的核心原因是正则匹配的指针移动逻辑:
- 原正则
/\b(\w+\s\w+)\b/ig每次匹配会消耗两个单词加中间空格的长度,匹配完成后指针直接跳到第二个单词的末尾位置,下一次匹配从该位置往后检索,自然会跳过以第二个单词开头的相邻配对,最终只能输出间隔的词对。 - 另外原代码里外层无意义的
while ($line)循环、未打开文件句柄就调用close的逻辑都是冗余代码,运行时会触发不必要的警告。
正确实现
推荐用先拆词再遍历配对的方案,逻辑清晰无正则奇技淫巧,后续维护成本低:
my $line = "The quick brown fox jumps over the lazy dog."; # 文本预处理:移除指定标点、统一转小写 $line =~ s/["",.]//ig; $line = lc($line); # 按空白切分,拿到所有单词的数组 my @words = split /\s+/, $line; my %wordcount; # 遍历到倒数第二个单词,依次和下一个单词拼接成相邻对 for my $i (0 .. $#words - 1) { my $pair = "$words[$i] $words[$i+1]"; print "$pair\n"; $wordcount{$pair} += 1; }
如果偏好正则实现,可以用零宽正向预查语法,预查部分不会消耗字符,匹配指针每次仅移动一个单词的长度,不会漏配对:
my $line = "The quick brown fox jumps over the lazy dog."; $line =~ s/["",.]//ig; $line = lc($line); my %wordcount; while ($line =~ m/\b(\w+)\b(?=\s(\w+)\b)/ig) { my $pair = "$1 $2"; print "$pair\n"; $wordcount{$pair} += 1; }
两种实现的输出完全符合预期,会按顺序输出所有相邻词对:
- the quick
- quick brown
- brown fox
- fox jumps
- jumps over
- over the
- the lazy
- lazy dog
内容的提问来源于stack exchange,提问作者7akeoverforce
相关产品推荐
相关产品推荐

