IF语句regex的值匹配(Perl)
我目前正在通过正则表达式行匹配表行从文件中的表中提取值IF语句regex的值匹配(Perl),regex,perl,if-statement,Regex,Perl,If Statement,我目前正在通过正则表达式行匹配表行从文件中的表中提取值 foreach my $line (split("\n", $file)) { if ($line =~ /^(\S+)\s*(\S+)\s*(\S+)$/) { my ($val1, $val2, $val3) = ($1, $2, $3); # $val's used here } } 为了代码清晰,我特意指定VAL。我的一些表格行包含10+个VAL(也称为列)-是否有更有效的方法来分
foreach my $line (split("\n", $file)) {
if ($line =~ /^(\S+)\s*(\S+)\s*(\S+)$/) {
my ($val1, $val2, $val3) = ($1, $2, $3);
# $val's used here
}
}
为了代码清晰,我特意指定VAL。我的一些表格行包含10+个VAL(也称为列)-是否有更有效的方法来分配VAL而不是执行…=($1,$2,$n)?列表上下文中的匹配将生成捕获组列表。如果失败,它将返回一个空列表,这是false。因此,你可以
if( my ( $val1, $val2, $val3 ) = $line =~ m/^(\S+)\s*(\S+)\s*(\S+)$/ ) {
...
}
然而,在这段代码中有许多明显的危险信号。该regexp捕获看起来非常类似于拆分:
if( my ( $val2, $val2, $val3 ) = split ' ', $line ) {
...
}
其次,为什么要按换行符拆分$file;如果您正在读取文件的内容,最好是一次实际读取一行:
while( my $line = <$fh> ) {
...
}
while(我的$line=){
...
}
看起来您只是在使用带有空格分隔符的表。您可以使用以下函数:
@valuearray=split(“,$line)
然后将这些要素描述为:
@valuearray[0]、@valuearray[1]
等..我假设这不是您的实际代码,因为如果是这样,它将无法工作:
foreach my $line (split("\n", $file)) {
if ($line =~ /^(\S+)\s*(\S+)\s*(\S+)$/) {
my ($val1, $val2, $val3) = ($1, $2, $3);
}
# all the $valX variables are now out of scope
}
您还应该知道,\s*
也将匹配空字符串,并可能导致细微错误。例如:
"a bug" =~ /^(\S+)\s*(\S+)\s*(\S+)$/;
# the captures are now: $1 = "a"; $2 = "bu"; $3 = "g"
尽管事实上\S+
是贪婪的,但锚定^$
将强制正则表达式进行匹配,从而允许空字符串拆分单词
如果您打算捕获所有由空格分隔的单词,那么使用split
是您的最佳选择,其他人已经提到过
open my $fh, "<", "file.txt" or die $!;
my @stored;
while (<$fh>) {
my @vals = split;
push(@stored, \@vals) if @vals; # ignore empty values
}
打开我的$fh,“?我一直喜欢他们使用split的地方-您的regexp似乎是一个候选项。我倾向于使用split/\s+/
@leonardoherra为什么?如果有空白的话,它只保留一个前导的空字段。小心地将ReExp替换为分裂,它们并不都意味着相同的东西,考虑如果代码> $Le==ABC-DEF,两者将产生什么;代码>感谢您的输入。您的第一个示例确实简化了代码,但是可读性是有争议的。我的示例中的正则表达式被简化了。我的一些表没有组成分隔符。初始文件被压缩成字符串,并删除其中的一部分以防止正则表达式匹配冲突。这就是为什么在我的示例中,文件最终被读取为字符串。@TLP-你说得对。我忘了split
对空格字符的处理与其他字符不同。谢谢您的输入。我提供的示例已简化-我报告中的分隔符实际上不一致。@kaspnord split支持完整的正则表达式。您可以在同一个表中使用任何分隔符,甚至不同的分隔符。谢谢您的输入。我已经更新了这个问题,以澄清$val变量的范围。示例中的拆分
是否处理不同数量的空格?不幸的是,我无法使用您的示例显式命名VAL。请参阅我对LeoNerd关于文件处理的帖子的评论。@kaspnord是的,拆分成一个数组可以保存任意数量的匹配项。尽管如果空格的数量是一个问题,例如“a\t\tc”应该是$val1=“a”$val3=“c”
(跳过$val2
),然后是否。不过,使用CSV模块可能会更好。如果不知道所需变量的数量,则使用数组。如果您觉得有必要,您可以轻松地计算数组元素,并在以后将它们分配给命名变量。可能不需要(通常不需要)对文件进行SLURP,这会降低性能。但这是另一个问题。