Найти файл, который не содержит конкретной строки - PullRequest
1 голос
/ 01 июля 2019

Я хочу найти файл, который не содержит конкретной строки? Перечисленный файл похож на ниже

../../../experiment/fileA.txt (contain word 'Book')
../../../experiment/fileB.txt (contain word 'Book')
../../../experiment/fileC.txt (do not contain word 'Book')
../../../experiment/fileD.txt (contain word 'Book')

Вот мой код

use strict;
use warning;

my $dirname = "../../../experiment/";
my $keyword = "Book";
my @result;

my $find_file = sub {
    my $F = $File::Find::name;
    if ($F =~ /txt$/) {
       open my $in, "<", $F or die $!;
       while(<$in>) {
          if (/\Q$keyword\E/){
             next;
          }else{
             push @result, $F;
             return;          
          }
      }
   }  
};

find ({ wanted => $find_file, no_chdir=>1}, $dirname );
foreach my $result (@result){
   chomp $result;
   $result =~ s{.*/}{};
   print "$result\n";
}   

Но, похоже, не работает. Он отображает весь файл, имеет ли он ключевое слово $ или нет. Я хочу, чтобы он отображался только в том случае, если в файле отсутствует ключевое слово $

Ответы [ 3 ]

5 голосов
/ 01 июля 2019

Там простая логическая ошибка.Код проходит через строки каждого файла

while (<$in>) {
    if (/\Q$keyword\E/){
        next;
    } else {
        push @result, $F;
        return;          
    }
}

и, как только любая строка не имеет $keyword, он добавляет файл в @result.

Вам нужно проверить все строки и, если $keyword никогда не будет найден, добавить файл.Самый простой способ сделать это - return из субмарина, как только вещь найдена

while (<$in>) {
    return if /\Q$keyword/;
}

push @result, $F;
2 голосов
/ 01 июля 2019

Это не относится к вашему коду, но я хотел бы отметить, что с помощью команды grep в любой системе Linux вы можете делать именно то, что вы пытаетесь сделать с этой командой:

grep -L Book -R ../../../experiment/
1 голос
/ 01 июля 2019

Path :: Iterator :: Rule делает такие задачи очень простыми. В качестве примечания я бы рекомендовал разрешить каталог до абсолютного пути перед итерацией.

use strict;
use warnings;
use Cwd 'abs_path';
use File::Basename;
use Path::Iterator::Rule;

my $dirname = abs_path "../../../experiment/";
my $keyword = "Book";

my $rule = Path::Iterator::Rule->new->not_dir->name(qr/txt$/)->not_line_match(qr/\Q$keyword\E/);
my $next = $rule->iter($dirname);
while (defined(my $file = $next->())) {
  print basename($file), "\n";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...