gpt4 book ai didi

regex - 为什么我的 Perl 正则表达式只找到最后一次出现的地方?

转载 作者:行者123 更新时间:2023-12-01 10:14:39 27 4
gpt4 key购买 nike

我对 Perl 脚本有以下输入,我希望在每个 <table>...</table> 中第一次出现 NAME="..."字符串结构。

整个文件被读入一个字符串,正则表达式作用于该输入。

但是,正则表达式总是返回最后一次出现的 NAME="..."字符串。任何人都可以解释发生了什么以及如何解决这个问题吗?

Input file: 
ADSDF
<TABLE>
NAME="ORDERSAA"
line1
line2
NAME="ORDERSA"
line3
NAME="ORDERSAB"
</TABLE>
<TABLE>
line1
line2
NAME="ORDERSB"
line3
</TABLE>
<TABLE>
line1
line2
NAME="ORDERSC"
line3
</TABLE>
<TABLE>
line1
line2
NAME="ORDERSD"
line3
line3
line3
</TABLE>
<TABLE>
line1
line2
NAME="QUOTES2"
line3
NAME="QUOTES3"
NAME="QUOTES4"
line3
NAME="QUOTES5"
line3
</TABLE>
<TABLE>
line1
line2
NAME="QUOTES6"
NAME="QUOTES7"
NAME="QUOTES8"
NAME="QUOTES9"
line3
line3
</TABLE>
<TABLE>
NAME="MyName IsKhan"
</TABLE>

Perl 代码从这里开始:

use warnings;
use strict;

my $nameRegExp = '(<table>((NAME="(.+)")|(.*|\n))*</table>)';

sub extractNames($$){
my ($ifh, $ofh) = @_;
my $fullFile;
read ($ifh, $fullFile, 1024);#Hardcoded to read just 1024 bytes.
while( $fullFile =~ m#$nameRegExp#gi){
print "found: ".$4."\n";
}
}

sub main(){
if( ($#ARGV + 1 )!= 1){
die("Usage: extractNames infile\n");
}
my $infileName = $ARGV[0];
my $outfileName = $ARGV[1];
open my $inFile, "<$infileName" or die("Could not open log file $infileName");
my $outFile;
#open my $outFile, ">$outfileName" or die("Could not open log file $outfileName");
extractNames( $inFile, $outFile );
close( $inFile );
#close( $outFile );
}

#call
main();

最佳答案

试试这个:

'(?><TABLE>\n+(?:(?!</TABLE>|NAME=).*\n+)*)NAME="([^"]+)"'

(?:.*\n+)*消耗任何不需要的行,而嵌入式前瞻——(?!</TABLE>|NAME=) -- 防止它超出第一个 NAME 字段或 TABLE 记录的末尾。以防万一有没有 NAME 字段的记录,我将大部分表达式包装在一个原子组中 -- (?>...) -- 防止无意义的回溯。

请注意,现在只有一个捕获组。最好只在真正需要捕捉某些东西时才使用它们;否则,使用非捕获品种:(?:...) .


编辑:至于为什么你的正则表达式不起作用,简短的回答是贪婪。匹配开始标签后,这部分接管:

((NAME="(.+)")|(.*|\n))*

最外层括号中的部分可以匹配任何内容:标签、NAME=行,换行——甚至是空行。将其包装在由贪婪控制的组中 * ,现在它匹配一切。那里没有任何东西可以让它在第一个 NAME 字段或什至在记录末尾停止匹配。

所以它实际上是“查找”NAME="..." 的出现字符串,但它是在一次消耗整个输入的单次匹配尝试中完成的。随着封闭 * 的每次迭代,捕获组被覆盖;完成后,最终的 NAME 值 -- MyName IsKhan -- 恰好留在第 4 组中。

我使用负前瞻来检查贪婪性,但您也可以使用非贪婪量词更直接地进行检查。这是我的正则表达式在不情愿的情况下的样子 *代替负面的前瞻:

'<TABLE>\n+(?:.*\n+)*?NAME="([^"]+)"'

不过,简单地切换到非贪婪量词对您的正则表达式没有帮助;您还必须进行一些结构更改。

关于regex - 为什么我的 Perl 正则表达式只找到最后一次出现的地方?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2468101/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com