2012-01-14 6 views
0

perlはgrep -nをエミュレートしますか?私はPerlと、このようにはgrepを-nエミュレートしたいために新しいです

が欲しい:

# egrep -n 'malloc\(|free\(|printf\(' test.c 
5:p = malloc(sizeof(char)); 
6:printf("Test\n"); 
7:free(p); 

があります

# perl grep.pl test.c 
malloc\(line 7 
free\(line 7 
printf(

Processed 10 lines 

スクリプト:どういうわけか

#!/usr/bin/perl 
$verbose = 1; 
@pattern = ('malloc\(', 'free\(', 'printf('); 
$counter = 0; 
open(FH, "<", $ARGV[1]) or die; 

while (<>) { 
    my $matches = (@pattern[0-2]); 
    $counter++; 
    # print "line $counter:$_" if ($_ =~ /malloc\(/o); 
    print join("line $counter\t\n",@pattern),"\n" if ($_ =~ /$matches/o); 
    close (FH); 
} 
print "\n"; 
$verbose == 1 && print "Processed $counter lines\n"; 

カウンターが間違っています。私はここで何が欠けていますか?

+3

ループ内で実行している「クローズ(FH)」とは何ですか? – Mat

+1

そして、読みは '<>'で行われ、 ' 'ではなく、' open(FH、 "<"、$ ARGV [1]) 'で始まります。 –

+1

なぜdownvotes?質問は明白であり、努力が示されている。私が知りたいのは、なぜOPがこれを最初にやりたいのかということだけです。 – Zaid

答えて

-1

これはトリックを行う必要があります。ただ、(そうでない場合は標準入力に使用される)ファイル名のオプション(malloc\()|(free\(')|(printf\()

+0

nice :)ありがとうございました!これは非常にきれいに見えます。オッズのために申し訳ありません。 – Juergen

+0

あなたは私にそれのポイントを与えることができます! –

+0

正規表現はコンパイルされません。 'printf'の後ろに括弧をエスケープする必要があります。また、OPのプログラムがうまくいかない理由について質問に答えなかった。 – Borodin

1

はあなたのコードでたくさん間違ってありますよう

#!/usr/bin/perl 

use strict; 

my $pattern=shift; 
my $fileName=shift; 

my $fh; 

if ($fileName) 
{ 
    open $fh, $fileName or die "Unable to open file $fileName"; 
} 
else 
{ 
    open $fh, '-'; 
} 

my $lineNumber = 1; 
while (<$fh>) 
{ 
    print sprintf("%4d %s", $lineNumber, $_) if (m%$pattern%); 
    ++$lineNumber; 
} 

はちょうどあなたのパターンを構築してパターンを渡していますが、

を追加することによって開始する必要があります
use strict; 
use warnings; 

プログラムの先頭にあります。すべての変数を宣言しなければなりませんが、Perl自身が最も簡単な問題の解決に役立ちます。 「自由(」 - -

$matches = (@pattern[0-2]); 

は、配列の最後から二番目の要素にアクセスする

$matches = $pattern[-2]; 

と同じである。そして、あなたが望むものではありませんこれは、$マッチに割り当てますあなたはまた、

$matches = join '|', @pattern; 

を書く場合

で、パターンの選択のいずれかに一致するパイプ演算子を使用することができます

私はjoinとは思わないと思います。最初の文字列を区切り文字として配列のすべての要素を結合しています。あなただけのマッチラインを望むなら、あなたは

print "line $counter\t$_\n" if /$matches/o; 

を必要としますが、私が言うように、働いたが取得する必要があることを、あなたのプログラムは、理想的な未満であると、私は必要な最小限の変化を示しています。

1

$という名前の変数があります。現在の行番号を含むので、その変数の値を出力するだけです!

perldoc perlvar 
3

以下は、Windowsでのgrepの基本的な実装です。おそらくあなたはあなたのために働くためにそれを微調整することができます。

perlの行番号は、$.(​​を参照)で与えられます。ダイアモンドオペレータを使用する場合、それは単にそのまま印刷することができます。複数のファイルを使用している場合しかし、それはファイル間で自動的にリセットされることはありません、あなたは魔法のビットを行う必要があります:

while (<>) { 
    # grep and print logic goes here 
    # e.g. print "$.: $_" if grep_match(); 

    close ARGV if eof; # this will reset $. for each file 
} 

コード:

use strict; 
use warnings; 
use v5.10; 

my $pattern  = shift; 

#use re 'debug'; 
# Refining the regex to allow using modifiers 
$pattern =~ s#^/##; 
if ($pattern =~ s{/([^/]+)$}{}) { 
    $pattern = "(?$1)$pattern"; 
} 

# Windows does not allow globbing, this is the fix 
for (@ARGV) { 
    unless (-e) { 
     @ARGV = win_args(@ARGV); 
     last; 
    } 
} 

my $found; 
while (<>) { 
    if (/$pattern/) { 
     unless ($found) { 
      say "----- $ARGV -----"; 
     } 
     print; 
     $found = 1; 
    } 
    $found = 0 if eof; 
} 

sub win_args { 
    return map glob, @_; 
} 
1

これがあればPerlでのコーディングのための練習をするために、perldocページは、関数がどのように使われ、ファイルが読み込まれ、$.のような特殊変数が使われているかを理解するのに役立ちます。要件は言語の能力の範囲内にあります。

ホイールを再発明しようとする場合は、付加価値を明確にする必要があります。

Windowsで* nixコマンドをエミュレートするためにこれが実行されている場合は、out there alreadyが何であれ満足していませんか?

+0

+1 Windowsに" findstr "コマンドがあることはまったく分かりませんでした。 – TLP

関連する問題