【问题标题】:matching regex using grep in perl在 perl 中使用 grep 匹配正则表达式
【发布时间】:2017-08-10 07:35:34
【问题描述】:

我在带有反引号的 perl 脚本中使用 grep。

grep -r --include=*.txt -e '[a-zA-Z0-9]*\.[a-zA-Z]*$' $dir -n >> test.txt;

我正在尝试过滤掉以文件名结尾的行。

示例: file1.txt 包含:

This is a file about file.txt
This file is about algorithms. 
File.txtbis contains several functions.
There are also several files. 
One of the files is sample.c
Another example is test.doc

我希望我的 grep 返回以下行:

This is a file about file.txt
One of the files is sample.c
Another example is test.doc

但是我的 grep 命令没有返回任何内容。

如果我删除了“$”符号,grep 命令会返回文件的所有行,即使它与正则表达式不匹配。

另外,我更愿意过滤掉 1 个或多个字符,而不是 0 个或更多,但 grep 只有 *.我可以在 grep 中使用“+”表示 1 个或多个字符吗?

在反引号中使用 grep 有限制吗?

【问题讨论】:

  • filter out lines that ends with a filename - 你是什么意思?扩大?任何扩展?
  • 我已经更新了描述。我指的是任何扩展名。
  • 将您的 -e 修改为 -P-E 替代。
  • 试试grep -Er --include=*.txt -e '[a-zA-Z0-9]+[.][a-zA-Z]+$' $dir -n >> test.txt;
  • 使用File::FindFile::Find::Rule 而不是运行grep

标签: perl grep


【解决方案1】:
#!/usr/bin/env perl

use File::Find qw( find );

# use File::Slurper qw( read_lines );

sub read_lines {
    my $file_name = shift;
    open my $fh, "<", $file_name or die "Couldn't open $file_name: $!";
    my @buf = <$fh>;
    close $fh;
    chomp @buf;
    return @buf;
}

find(
    {
        no_chdir => 1,
        wanted   => sub {
            my $file_path = $File::Find::name;
            next unless -f $file_path;
            my $file_name = $file_path;
            $file_name =~ s/^.*\///;    # drop everything until last '/'

            for ( read_lines($file_path) ) {
                print "$_\n" if m/\Q$file_name\E\s*$/;
            }
        },
    },
    '.'
);

如果你需要引用其他文件,只需在查找之前累积文件名,如下所示:

#!/usr/bin/env perl

use File::Find qw( find );

# use File::Slurper qw( read_lines );

sub read_lines {
    my $file_name = shift;
    open my $fh, "<", $file_name or die "Couldn't open $file_name: $!";
    my @buf = <$fh>;
    close $fh;
    chomp @buf;
    return @buf;
}

my @file_paths = ();

find(
    {
        no_chdir => 1,
        wanted   => sub {
            my $file_path = $File::Find::name;
            next unless -f $file_path;
            push @file_paths, $file_path;
        },
    },
    '.'
);

my @file_names = map {
    my $file_name = $_;
    $file_name =~ s/^.*\///;    # drop everything until last '/'
    $file_name;
} @file_paths;

my $regexp = '(?:' . join( '|', map { "\Q$_\E" } @file_names ) . ')$';
$regexp = qr/$regexp/;

for my $file_path (@file_paths) {
    for ( read_lines($file_path) ) {
        print "$_\n" if /$regexp/;
    }
}

【讨论】:

  • @chris-yo,如果这有帮助,请按答案旁边的复选标记将其标记为已接受。谢谢!
【解决方案2】:

grep -Er --include=*.txt -e '[a-zA-Z0-9]+.[a-zA-Z]+$' $dir -n >> test.txt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多