1

我的程序包含ascii.txt以匹配其中的模式。我的程序是实现sed命令,只是为了尝试编写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因为 REGEX 存储在标量变量中,所以不执行

ascii.txt包含

Test 1
REGEX TEST

当我print $scriptsearch_print_lines子程序中使用时,它会打印用户发送的正则表达式

4

2 回答 2

3

当您在命令行中传入某些内容并在脚本中使用它时,将使用整个文字文本。因此,如果您传入/Test/,它会将这些斜杠视为文字,因此它正在查看的“真实”正则表达式类似于\/Test\/(转义斜杠,因为现在它正在寻找它们。尝试传入不带 // 包围它的正则表达式.

如果您的目标是允许 // 显示它是一个正则表达式,我会在程序启动时删除它们。

另一个编辑:如果您希望能够传入标志,则需要以某种方式评估输入。

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

进而

"REGEX TEST" =~ $regex

应该返回真。但是,进行这样的评估是非常不安全的。

编辑:发生的事情eval是执行块中的任何内容。所以在上面的 eval 中发生的是你动态地创建一个正则表达式并将它设置为一个变量。这允许您使用像 i 这样的正则表达式标志,而无需对命令行输入进行任何特殊解析。执行 eval 时,就好像您输入了$regex = /Test/i. 然后你可以比较你的文本$regex,它会起作用。我考虑了这一点,因为除非您设置 i 标志以使比较不区分大小写,否则您的示例将不起作用。

于 2013-08-02T22:49:04.263 回答
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);
    }
}
于 2013-08-02T23:01:34.610 回答