2013-08-02 175 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相同; –