Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
IF语句regex的值匹配(Perl)_Regex_Perl_If Statement - Fatal编程技术网

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,这会降低性能。但这是另一个问题。