需要遍历目录-删除与模式匹配的行

时间:2019-04-03 01:17:52

标签: perl

需要遍历Unix目录并搜索每个文件中的每一行。如果存在模式匹配,请删除该行。无法删除行,所以我只是试图找到模式并替换为另一个。

使用文件名填充数组并进行遍历。我有一个计数器,它正在查看每个文件中的每一行(至少它们计数正确)。

#!/usr/bin/perl -l
#!/usr/bin/perl -i.bak -w
#!/usr/bin/env perl

use strict;
use warnings;
use File::Find;

# 4-1-19
# pfs
# remove lines with dental code ADD2999 from all HMO Max load files in /home/hsxxx/dat/feeLoad directory

$| = 1;


chdir "/home/hstrn/dat/feeLoad";
chdir;


my $dir  = </home/hstrn/dat/feeLoad/>;
my @files;
my $count=0;

opendir(DIR, $dir) or die "Cannot open directory $dir, Perl says $!\n";

while (my $file = readdir DIR)
{
        push @files, "$dir/$file" unless -d "$dir/$file";
}

closedir DIR;

{
local @ARGV = @files;
while (<>)
{
        s/ADD2999/sometext/g;
        $count++;
}
print "Total lines read are: $count";

}

希望所有字符串ADD2999都被替换为文本

2 个答案:

答案 0 :(得分:2)

要删除行,需要在写入新文件时避免打印它们。您的代码根本不会写入任何文件?


这可能是现有工具的工作。

find /home/hstrn/dat/feeLoad -maxdepth 1 -type f \
   -exec perl -i~ -ne'print if !/ADD2999/' {} +

如果要避免创建备份,请使用-i代替-i~。我更喜欢创建备份,然后在确认一切正常后将其删除。

显示将要删除的文件:

find /home/hstrn/dat/feeLoad -maxdepth 1 -type f -name '*~'

删除文件:

find /home/hstrn/dat/feeLoad -maxdepth 1 -type f -name '*~' -delete

答案 1 :(得分:0)

这是我第一次尝试解决该问题,但是它可能会使用更多的极端情况检查。例如。您如何处理受写保护的文件等。它还假定文件足够小,可以放入内存进行处理。

#!/usr/bin/perl
use warnings;
use strict;
use autodie;

use File::Spec;
use File::Slurper qw(read_text write_text);

my $count = 0;
my $dir = "tmp";

opendir(my $dh, $dir);
while (readdir $dh) {
    # skip anything that shouldn't be processed
    next if /^\.\.?$/; # . && ..
    my $file = File::Spec->catfile($dir, $_);
    next if -d $file;  # directories

    # slurp file content and replace text
    my $content = read_text($file);
    my $matches = ($content =~ s/ADD2999/sometext/g);

    # count lines
    my @eols = ($content =~ /(\n)/g);
    $count += @eols;

    # replace original file if contents were modified
    write_text($file, $content) if $matches;
}
closedir($dh);

print "Total lines read are: $count\n";

exit 0;

试运行:

$ wc -l tmp/test*.txt
  5 tmp/test2.txt
  6 tmp/test.txt
 11 total
$ fgrep ADD2999 tmp/*.txt
tmp/test2.txt:asddsada ADD2999 asdsadasd
tmp/test2.txt:21312398 ADD2999 dasdas

$ perl dummy.pl
Total lines read are: 11

$ fgrep ADD2999 tmp/*.txt
$ fgrep sometext tmp/*.txt
tmp/test2.txt:asddsada sometext asdsadasd
tmp/test2.txt:21312398 sometext dasdas

如果文件很大,则需要使用逐行处理方法(仅显示循环的内容)。副作用是所有文件都会被触摸,尽管其中可能没有任何替换内容。

# read file and replace text
open(my $ifh, '<', $file);
my $tmpfile = File::Spec->catfile($dir, "$_.$$");
open(my $ofh, '>', $tmpfile);
while (<$ifh>) {
    s/ADD2999/sometext/g;
    print $ofh $_;
}
$count += $.; # total lines in $ifh
close($ofh);
close($ifh);

# replace original file with new file
unlink($file);
rename($tmpfile, $file);