3

以下のようなファイルがあるとしましょう:

そして、すべての10進数をハッシュに格納したいと思います。

hello world 10 20
world 10 10 10 10 hello 20
hello 30 20 10 world 10

私はこれを見ていまし

そしてこれはうまくいきました:

> perl -lne 'push @a,/\d+/g;END{print "@a"}' temp
10 20 10 10 10 10 20 30 20 10 10

次に、必要なのは、各正規表現の発生数をカウントすることでした。

このためには、すべての一致をハッシュに格納し、すべてのキーに増分値を割り当てる方がよいと思います。

だから私は試しました:

perl -lne '$a{$1}++ for ($_=~/(\d+)/g);END{foreach(keys %a){print "$_.$a{$_}"}}' temp

これにより、次の出力が得られます。

> perl -lne '$a{$1}++ for ($_=~/(\d+)/g);END{foreach(keys %a){print "$_.$a{$_}"}}' temp
10.4
20.7

私が間違っていたところはどこでも誰かが私を訂正できますか?

私が期待する出力は次のとおりです。

10.7
20.3
30.1

これはawkで実行できますが、perlでのみ実行したいと思います。

また、出力の順序は私には関係ありません。

4

2 に答える 2

5
$a{$1}++ for ($_=~/(\d+)/g);

これは

$a{$_}++ for ($_=~/(\d+)/g);

と簡略化できます

$a{$_}++ for /\d+/g;

この理由は、/\d+/gが一致のリストを作成し、それを によって反復処理するためforです。現在の要素は にあり$_ます。最後の試合でそこに残っていたものは何でも含まれると思い$1ますが、この場合は絶対に使用したくないものです。

于 2013-01-31T10:55:34.580 に答える
4

別のオプションは次のとおりです。

$a{$1}++ while ($_=~/(\d+)/g);

これは、あなたのコードが行うことを期待していると思います。一致が発生すると、成功した各一致をループします。したがって、$1それはあなたが思うものになります。

違いを明確にするために:

Perlの単一引数forループは、「リストの各要素に対して何かを行う」ことを意味します。

for (@array)
{
    #do something to each array element
}

したがって、コードでは、一致のリストが最初に作成され、一致のリスト全体が見つかった後にのみ、結果に対して何かを行う機会がありました。 $1リストが作成されるたびに一致ごとにリセットされましたが、コードが実行されるまでに、その行の最後の一致に設定されていました。それがあなたの結果が意味をなさない理由です。

一方、while ループは「この条件が true かどうかを毎回チェックし、条件が false になるまで続ける」ことを意味します。したがって、while ループ内のコードは、正規表現の$1一致で実行され、その一致の値を持ちます。

この違いが Perl で重要になるもう 1 つの時間は、ファイル処理です。for (<FILE>) { ... }最初にファイル全体をメモリに読み込みますが、これは無駄です。代わりに使用することをお勧めします。これはwhile (<FILE>)、ファイルを 1 行ずつ調べて、必要な情報のみを保持するためです。

于 2013-01-31T11:09:35.027 に答える