通常,正则表达式搜索将从我提供的字符串的开头搜索匹配项。在这种特殊情况下,我使用一个非常大的字符串(最多几兆字节),我想对该字符串运行连续的正则表达式搜索,但从特定索引开始。
现在,我知道我可以使用substr
功能简单地丢弃我想要从搜索中排除的部分,但我担心这不是很效率很高,因为我会做几千次。
我想要使用它的特定目的是在一个非常大的文本中跳转单词,跳过空白(无论它是否是简单的空格,制表符,换行符等)。我知道我可以使用split函数通过传递\s+
作为分隔符将文本拆分为单词,但这会让我以后更加复杂,因为还有其他各种可能的单词分隔符,例如引号(好吧,我在这里使用了术语' word'有点慷慨),所以如果我可以在同一个字符串上使用连续的正则表达式搜索从一个单词跳到另一个单词,对我来说会更容易,总是指定下一个索引,以便我开始查看。这在Perl中是可行的吗?
答案 0 :(得分:2)
所以你想要匹配文本正文的单词。
(示例找到包含i
的单词。)
您认为拥有单词的起始位置会有所帮助,但它并不有用。以下说明了获取这些职位并使用它们的看法:
my @positions;
while ($text =~ /\w+/g) {
push @positions, $-[0];
}
my @matches;
for my $pos (@positions) {
pos($text) = $pos;
push @matches $1 if $text =~ /\G(\w*i\w*)/g;
}
如果根本不使用起始位置会更简单。除了更简单之外,我们还不再需要两种不同的正则表达式模式来同意构成单词的内容。结果如下:
my @matches;
while ($text =~ /\b(\w*i\w*)/g) {
push @matches $1;
}
或
my @matches = $text =~ /\b(\w*i\w*)/g;
然而,更好的想法是提前自己添加单词。这种方法允许更简单的模式和更高级的定义" word" [1] 。
my @matches;
while ($text =~ /(\w+)/g) {
my $word = $1;
push @matches, $word if $word =~ /i/;
}
或
my @matches = grep { /i/ } $text =~ /\w+/g;
答案 1 :(得分:0)
如果没有更多信息,我只能建议pos
function
在进行全局正则表达式搜索时,引擎会保存上一个匹配结束的位置,以便它知道从哪里开始搜索下一次迭代。 pos
函数可以访问该值并允许显式设置,以便后续的m//g
将开始查看指定的位置而不是字符串的开头
这个程序给出了一个例子。在每个偏移列表之后搜索字符串以查找第一个非空格字符,并显示找到的字符(如果有)
请注意,全局匹配必须在标量上下文中完成,此处由if
应用,以便仅报告下一个匹配项。否则,全局搜索将仅运行到文件的末尾,并仅保留有关最后一个匹配的信息
use strict;
use warnings 'all';
use feature 'say';
my $str = 'a b c d e f g h i j k l m n';
# 0123456789012345678901234567890123456789
# 1 2 3
for ( 4, 31, 16, 22 ) {
pos($str) = $_;
say $1 if $str =~ /(\S)/g;
}
c
l
g
i