2013-08-02 50 views
1

我的程序包含ascii.txt以匹配來自它的模式。 我的程序是執行sed命令,只是爲了嘗試編寫perl代碼,因爲我正在學習perl。在Perl中匹配正則表達式

#!/usr/bin/perl 
# sed command implementation 
use strict; 
use warnings; 
use subs qw(read_STDIN read_FILE usage); 
use IO::File; 
use constant { 
    SEARCH_PRINT => 0, 
}; 

our $proj_name = $0; 

main(@ARGV); 

sub main 
{ 
    if(scalar @_ == 2) { 
     read_FILE @_; 

    } 
    else { 
     usage 
    } 
} 

sub read_FILE { 
    my ($sed_script, $file_name) = @_; 
    my $parsed_val = parse_sed_script($sed_script); 
    if($parsed_val == SEARCH_PRINT) { 
     search_print_lines($sed_script, $file_name); 
    } 
} 

sub parse_sed_script { 
    my $command = shift or return; 
    if($command =~ /^\/([^\/].)*\/$/) { 
     return SEARCH_PRINT; 
    } 
} 

sub search_print_lines { 
    my ($script, $file) = @_; 
    my $fh = IO::File->new($file, "r") or error("no file found $file"); 
    while($_ = $fh->getline) { 
     print if $_ =~ $script 
    } 
} 

sub usage { 
    message("Usage: $proj_name sed-script [file]") 
} 

sub error 
{ 
    my $e = shift || 'unkown error'; 
    print("$0: $e\n"); 
    exit 0; 
} 

當我從shell執行:sed.pl /Test/ ascii.txt

我發現print if $_ =~ $script,不會因爲正則表達式的執行存儲在標量

ascii.txt包含。

Test 1 
REGEX TEST 

當我使用print $scriptsearch_print_lines子程序它打印用戶

回答

3

當你在命令行上傳遞的東西,在你的腳本中使用它發送的正則表達式,則使用整個文字文本。所以如果你通過/Test/,它會將這些斜線看作文字,所以它所看到的「真正的」正則表達式就像\/Test\/(跳過斜槓,因爲現在它正在尋找它們)。嘗試傳遞正則表達式周圍

如果你的目標是讓//表明這是一個正則表達式,在程序啓動時我就刪除它們

還有一個編輯:如果你希望能夠通過在標誌,你需要以某種方式評估輸入。

$script = '/Test/i'; 
eval { "\$regex = $script" }; 

然後

"REGEX TEST" =~ $regex 

應該返回true。不過,做這樣的評估是非常不安全的。

編輯:在eval中發生的事情是,塊中的任何內容都被執行。所以在上面的eval中發生的事情是,你動態創建一個正則表達式並將其設置爲一個變量。這允許您使用像i這樣的正則表達式標誌,而不必對命令行輸入做任何特殊的分析。當執行eval時,就好像你輸入了$regex = /Test/i。然後你可以比較你的文字$regex,它會工作。我想過這個,因爲你的例子不會工作,除非你設置了i標誌來使比較不區分大小寫。

+0

我不明白,我需要一些解釋。 –

+0

如果你發送「/ Test /」,它不會匹配「REGEX TEST」,因爲「REGEX TEST」不包含任何斜槓。那有意義嗎?如果這是你不瞭解的其他內容,請告訴我,我會盡力澄清。 – Jeremy

+0

是的,我知道這一點,但我不明白/ \/$ script \ //和eval? –

1

您沒有從$ sed_script變量中刪除斜槓。在我修改了read_FILE函數之後,它開始工作:

sub read_FILE { 
    my ($sed_script, $file_name) = @_; 
    my $parsed_val = parse_sed_script($sed_script); 

    if($parsed_val == SEARCH_PRINT) { 
     $sed_script =~ s/^\/(.*)\/$/$1/; 

     #you can also parse the regexp 
     #$sed_script = qr/$sed_script/; 
     search_print_lines($sed_script, $file_name); 
    } 
} 
+0

它工作正常,但是//錯在什麼地方,爲什麼如果//被刪除會工作? –

+0

@UNIX它不搜索'Test',而是'/ Test /' – user4035

+0

如果它是真的,當我用打印替換我的代碼時if $ _ =〜/ Test /; 它的工作原理是 ,它與$ _ =〜$ script相同; –