греп від одного, але не від іншого


2

Як викрити вміст файлу з іншого файлу

Скажіть, у мене є файл "file1" і він є

a
b
c

і ще один файл "file2", який має

a
b
c
d
e
f

Я б зазвичай робив

cat file2 | grep -v a | grep -v b | grep -v c 

Чи можна це зробити з файлами

grep -v file2 file1

Відповіді:


5

Використовуйте diffдля пошуку відмінностей та sedвибору, форматування та друку лише доданих рядків:

diff file1 file2 | sed -n "/^>/{s/> //;p}"

Додано:

Якщо файли мають різні порядки, то sortспочатку їх обидва, потім diffїх.

sort file1 > file1.s
sort file2 > file2.s
diff file1.s file2.s | sed -n "/^>/{s/> //;p}"

Якщо ви використовуєте bash, ви можете використовувати <(...)заміну процесу:

diff <(sort file1) <(sort file2) | sed -n "/^>/{s/> //;p}"

Це дуже розумно. Однак проблема трохи не вказана. Що робити, якщо рядки в двох файлах були в різному порядку?
dangph

2

GNU grep (а я думаю, що і інші) може скористатися -fможливістю:

   -f FILE, --file=FILE
          Obtain patterns from FILE, one  per  line.   The  empty
          file  contains  zero  patterns,  and  therefore matches
          nothing.  (-f is specified by POSIX.)

Отже, ви могли це зробити:

grep -vFf file1 file2 

Після пропозиції Ніколь Гамільтон у коментарях я додав опцію '-F', яка змушує греп інтерпретувати її ПАТРЕТ (у цьому випадку кожен рядок у файлі1) як фіксовані рядки, а не регулярні вирази:

  -F, --fixed-strings
          Interpret PATTERN as  a  list  of  fixed  strings,  separated  by
          newlines,  any  of  which  is to be matched.  (-F is specified by
          POSIX.)

Я також написав сценарій PERL з кількома іншими параметрами:

$ list_compare.pl -h

  USAGE: compare_lists.pl FILE1 FILE2

  This script will compare FILE1 and FILE2, searching for the 
  contents of FILE1 in FILE2 (and NOT vice-versa). FILE one must 
  be one search pattern per line, the search pattern need only be 
  contained within one of the lines of FILE2.

OPTIONS: 
  -c : Print patterns COMMON to both files
  -f : Search only the first characters (until the 1st space) of each line of 
       FILE2 for the search pattern given in FILE1. So, if FILE1 contains
       "foo bar", only "foo" will be taken as a pattern (MUCH faster).
  -d : Print duplicate entries     
  -m : Print patterns MISSING in FILE2 (default)
  -h : Print this help and exit

1
+1 -fВаріант - досить гарна ідея. Але ви, ймовірно, захочете використовувати fgrepне grepтак, що рядки, з якими ви читаєте -f, трактуватимуться як буквальний текст, а не зразки зворотного вираження.
Ніколь Гамільтон

@NicoleHamilton, і це просто пояснило дивну поведінку, з якою я отримував за ці роки, grep -fі причину, коли я написав цей сценарій Perl в першу чергу! Дякую, я не зрозумів, що він розглядає рядки файлу як регулярні вирази. Змінено питання використання grep -Ff(fgrep амортизується каже man grep).
тердон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.