Нужно перебрать каталог - удалить строки, которые соответствуют шаблону - PullRequest
0 голосов
/ 03 апреля 2019

Необходимо перебрать каталог 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 ]

2 голосов
/ 03 апреля 2019

Чтобы удалить строки, вам нужно избегать их печати при записи в новый файл.Ваш код вообще не записывает ни в какие файлы ???


Это может быть работа для существующих инструментов.

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
0 голосов
/ 03 апреля 2019

Это будет моя первая попытка решить проблему, но она может использовать еще одну проверку угловых случаев.Например, как вы обрабатываете файлы, защищенные от записи, и т. Д. Также предполагается, что файлы достаточно малы, чтобы помещаться в память для обработки.

#!/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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...