Следующее работает, если имена файлов в fileA
указаны ровно по одному в строке И имена файлов не содержат символов перевода строки(\n
):
$ xargs -d'\n' <fileA \
perl -MFile::Slurp -e '
my @patterns=read_file(shift, {chomp=>1});
$re = join ("|",@patterns);
while (<>) {
if (m/$re/o) { readline; next };
print
}' fileB
9606.jklpan
how is the weather
10116.zyxtak
i am happy to see rainbow
xargs
используется для предоставления списка аргументов имени файла Perl-скрипту, считывая в fileA
по одной строке за раз.
Perl-скрипт начинается с чтения первого аргумента имени файла в командной строке(fileB
)и построения регулярного выражения, объединяющего каждую строку (послеchomp
-ввода символа новой строки, заканчивающего каждую входную строку ).
После этого он перебирает все оставшиеся аргументы имени файла,пропуская все совпадающие строки, а следующая строка --печатает оставшиеся строки.
Обратите внимание, что этот сценарий просто выводит выходные данные из всех входных файлов в стандартный вывод и не пытается различать выходные данные из разных входных файлов.
Если вы хотите, чтобы вывод из каждого входного файла направлялся в другой выходной файл (, например. вывод из файла 234
попадет в 234.new
), вы можете заменить весь цикл while (<>) {...}
чем-то вроде этого:
my $lastfn="";
while (<>) {
if(eof) { close(OUTFILE) };
if ($lastfn != $ARGV) {
$lastfn=$ARGV;
open(OUTFILE,">","$ARGV.new")
};
if (m/$re/o) { readline; next; };
print OUTFILE
}
или если вы просто хотите, чтобы имена файлов отображались в выводе:
my $lastfn="";
my $nl=""; # we dont want to print a LF before the first output filename
while (<>) {
if ($lastfn != $ARGV) {
print "$nl", $ARGV,":\n";
$nl="\n";
$lastfn=$ARGV };
};
if (m/$re/o) { readline; next };
print
}
или с префиксом имени входного файла перед каждой строкой вывода:
while (<>) {
if (m/$re/o) { readline; next };
print "$ARGV:$_"
}
Наконец, это можно сделать полностью внутри perl, без использования xargs:
$ perl -MFile::Slurp -e '
my @patterns=read_file(shift, {chomp=>1});
$re = join ("|",@patterns);
my @files=read_file(shift, {chomp=>1});
@ARGV=@files;
while (<>) {
if (m/$re/o) { readline; next };
print
}' fileB fileA