2

現在、テーブルの行に対するREGEX行の一致を介して、ファイル内のテーブルから値を抽出しています。

foreach my $line (split("\n", $file)) {
    if ($line =~ /^(\S+)\s*(\S+)\s*(\S+)$/) {
        my ($val1, $val2, $val3) = ($1, $2, $3);

        # $val's used here
    }
}

コードをわかりやすくするために、意図的に値を割り当てています。私のテーブル行のいくつかには10以上の値(別名列)が含まれています-... =($ 1、$ 2、...、$ n)を実行する代わりに、値を割り当てるより効率的な方法はありますか?

4

3 に答える 3

9

リストコンテキストで一致すると、キャプチャグループのリストが生成されます。失敗すると、空のリストが返されますが、これはfalseです。したがって、あなたはすることができます

if( my ( $val1, $val2, $val3 ) = $line =~ m/^(\S+)\s*(\S+)\s*(\S+)$/ ) {
   ...
}

ただし、このコードにはいくつかの危険信号があります。その正規表現キャプチャは、分割と非常によく似ています。

if( my ( $val2, $val2, $val3 ) = split ' ', $line ) {
   ...
}

次に、$fileを改行で分割する理由。ファイルの内容を読み取る場合は、実際に一度に1行を読み取る方がはるかに優れています。

while( my $line = <$fh> ) {
   ...
}
于 2012-04-18T14:48:56.053 に答える
2

これは実際のコードではないと思います。そうであれば、機能しないからです。

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
}

これにより、キャプチャされた値が 2 次元配列に格納されます。なんらかの理由で実際にファイル全体をメモリに格納する必要がない限り、ファイル ハンドルを直接使用して行単位で読み取る方法が推奨されます。

于 2012-04-18T15:16:57.077 に答える
1

スペース区切り文字を含むテーブルを使用しているように見えます。分割機能 を使用できます。

@valuearray = split(" ", $line)

次に、要素を次のようにアドレス指定します。

@valuearray[0] ,@valuearray[1]等..

于 2012-04-18T14:52:28.010 に答える