2012-01-14 78 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 2012-01-14 16:41:05

+1

開頭(FH,「<」,$ ARGV [1])'首先是什麼,因爲讀取是從<<>而不是''完成的? – 2012-01-14 16:57:40

+1

爲什麼downvotes?問題是明確的,並且已經顯示出努力。我想知道的唯一事情就是OP爲什麼要首先做到這一點。 – Zaid 2012-01-14 19:54:26

回答

-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; 
} 

只是構建您的圖案(malloc\()|(free\(')|(printf\()

+0

不錯:)謝謝大家!這個看起來很乾淨。抱歉的機率。 – Juergen 2012-01-14 17:15:13

+0

你可以給我一個點! (也許是一個勾號!) – 2012-01-14 17:22:35

+0

正則表達式不會編譯 - 你需要在'printf'之後轉義括號。此外,您還沒有回答OP的程序不起作用的問題。 – Borodin 2012-01-14 17:24:52

1

有你的代碼錯誤很多通的格局,但你應該加入

啓動
use strict; 
use warnings; 

在程序的開頭。你將不得不聲明所有的變量,但Perl本身將幫助你解決最微不足道的問題。

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

相同

$matches = $pattern[-2]; 

從數組結束訪問第二元素 - 「自由(」 - 並將其分配到$比賽,這是你想要你不是。可以使用它匹配任何選擇的模式的管道運營商,如果你寫

$matches = join '|', @pattern; 

此外,在

print join("line $counter\t\n",@pattern),"\n" if ($_ =~ /$matches/o); 

我不認爲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 2012-01-15 00:14:03