Удалить совпадающую строку и одну последовательную строку (цикл for)

У меня была такая же проблема после того, как я установил git завершение . Проблема решена путем комментирования этих строк в .bashrc:

.
#Git completion script
#for file in /etc/bash_completion.d/* ; do 
#       source "$file"
#done

Итак, теперь все работает четко:

user@linux~>

и нет

 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
 have: command not found
-1
25.08.2019, 06:53
3 ответа

Насколько я понял, у вас есть несколько файлов, и их имена хранятся в файле с именем fileA, а затем вы хотите распечатать все из каждого файла, кроме текста, хранящегося в fileB, поэтому вы можете сделать:

while read -r file_name
do
grep -v -f <(grep -A1 -f fileB "$file_name") "$file_name"
done < file

Содержимое будет распечатано на stdout.

0
28.01.2020, 05:12

Следующее работает, если имена файлов в 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
0
28.01.2020, 05:12

Мы подойдем к этой проблеме, сначала создав файл команд sed, проверив файл B, а затем применив этот файл команд к файлам, перечисленным в файле A.

Здесь следует отметить, что мы цитируем содержимое файла B, потому что оно должно быть допустимым синтаксисом sed при последующем использовании.

$ sed -e '
   s:[][\/.^$*]:\\&:g
   s:.*:/&/{$q;N;d;}:
' < fileB > cmds

$ < fileA xargs -d'\n' -r -l sed -f cmds

Вот еще один подход к вашей проблеме: мы сохраняем строки файла B как ключи хеша, а затем при чтении файлов, перечисленных в файле A, проверяем, не найден ли какой-либо ключ.

$ < fileA xargs -d'\n' -r \
   perl -ne 'BEGIN { $argc = @ARGV - 1; }
       @ARGV == $argc and $h{$_}++,next;
       print,close(ARGV) if eof;
       my $n = <>;
       print $_,$n if ! exists $h{$_};
' fileB
0
28.01.2020, 05:12

Теги

Похожие вопросы