2

私の課題はタイトルよりも少し掘り下げていますが、タイトルには私の主な質問があります。割り当ては次のとおりです。

ファイル/ディレクトリリスト内のすべての通常ファイルと、ファイル/ディレクトリリスト内のディレクトリの下にあるすべての通常ファイルで、正規表現のすべての出現を grep する perl スクリプトを作成します。ファイルが TEXT ファイルでない場合は、最初に UNIX コマンド文字列(スイッチなし) でファイルを操作し、結果の行を検索する必要があります。-l スイッチが指定されている場合、正規表現を含むファイルのファイル名のみが 1 行に 1 つずつ表示されます。この場合、ファイル名は最大 1 回出現する必要があります。-l スイッチが指定されていない場合、一致するすべての行が出力され、それぞれがファイル名とコロンによって同じ行に進みます。コマンド ラインからの呼び出しの例:

plgrep 'ba+d' file1 dir1 dir2 file2 file3 dir3

これが私のコードです:

#!/usr/bin/perl -w

use Getopt::Long;
my $fname = 0;
GetOptions ('l' => \$fname);

$pat = shift @ARGV;
while (<>) {
    if (/$pat/) {
        $fname ? print "$ARGV\n" : print "$ARGV:$_";
    }
}

これまでのところ、このコードは、非テキスト ファイルの読み取りと、-l スイッチを使用した場合のファイル名の重複の出力を除いて、想定されているすべてのことを行います。コマンド ラインで次のように入力した後の出力例を次に示します。plgrep 'ba+d' file1 file2

  • file1:私の犬は悪いです。
  • file1:私の犬はとてもひどいです。
  • file2:ギターが下手です。
  • file2:ギターは下手だけど弾いてて楽しい!

これは完璧です!しかし、-l スイッチを使用してファイル名のみを出力すると、コマンド ラインで次のように入力すると、次のようになります: plgrep -l 'ba+d' file1 file2

  • ファイル1
  • ファイル1
  • ファイル2
  • ファイル2

これらの重複を取り除き、印刷するだけにするにはどうすればよいですか:

  • ファイル1
  • ファイル2

私が試してみました:

$pat = shift @ARGV;
while (<>) {
    if (/$pat/) {
        $seen{$ARGV}++;
        $fname ? print "$ARGV\n" unless ($seen{$ARGV} > 1); : print "$ARGV:$_";
    }
}

しかし、 -l スイッチなしで実行しようとすると、次のようになります。

  • file1:私の犬は悪いです。
  • file2:ギターが下手です。

私も試しました:

$fname ? print "$ARGV\n" not ($ARGV > 1) : print "$ARGV:$_";

しかし、"$ARGV\n" の近くの plgrep の 17 行目で構文エラーが発生し続けます。

誰かが重複の問題と課題のイタリック体の部分で私を助けてくれたら、本当に感謝しています. そのイタリック体の部分のどこから始めればよいかさえわかりません。

4

2 に答える 2

1

ファイル名だけを出力している場合はlast、ファイルが一致することが既にわかっているため、最初の一致後に (コマンドを使用して) ループを終了できます。ファイルの残りの部分をスキャンしないことで、名前が繰り返し印刷されるのを防ぐこともできます。

追加するために編集:この方法で行うには<>、ファイルを読み取るために使用することから、代わりに名前を取得し@ARGVopen通常どおり ing に切り替える必要もあります。

を引き続き使用したい場合<>は、代わりに変更を監視$ARGVし (新しいファイルの読み取りを開始したことを示します)、現在のファイルがまだ一致するファイルを見つけたかどうかを示すフラグを保持する必要があります。ただし、このアプローチでは、すべてのファイル全体を読み取る必要があり、少なくとも 1 つの一致が含まれているかどうかを確認するのに十分な量の各ファイルのみを読み取る (つまり、最初の一致の後に次のファイルにスキップする) よりも効率が悪くなります。 )、代わりに切り替えることをお勧めしopenます。

于 2013-03-04T07:02:44.200 に答える
0

最初の構文の問題は、余分なセミコロンです。

2 つ目は、if/unless をステートメントの末尾のステートメント修飾子としてのみ使用できることです。そのように条件文の途中に埋め込むことはできません。

$fname ? print "$ARGV\n" unless ($seen{$ARGV} > 1); : print "$ARGV:$_";

なる:

next if $seen{$ARGV} > 1;
print $fname ? "$ARGV\n" : "$ARGV:$_";
于 2013-03-05T16:22:28.060 に答える