grep de um, mas não do outro

2

Como faço para grep OUT o conteúdo de um arquivo de outro arquivo

Digamos que eu tenha um arquivo "file1" e tenha

a
b
c

e outro arquivo "file2" que tem

a
b
c
d
e
f

Eu costumava fazer

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

Existe uma maneira de fazer isso com os arquivos

grep -v file2 file1
    
por cripto 09.12.2012 / 06:23

2 respostas

5

Use diff para encontrar as diferenças e sed para selecionar, formatar e imprimir apenas as linhas adicionadas:

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

Adicionado:

Se os arquivos estiverem em ordens diferentes, sort os dois primeiro e, em seguida, diff deles.

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

Se você estiver usando bash , poderá usar a substituição do processo <(...) :

diff <(sort file1) <(sort file2) | sed -n "/^>/{s/> //;p}"
    
por 09.12.2012 / 07:09
2

O GNU grep (e eu imagino outros também) pode pegar a opção -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.)

Então, você poderia fazer isso:

grep -vFf file1 file2 

Seguindo a sugestão Nicole Hamilton nos comentários, adicionei a opção '-F' que faz com que o grep interprete seu PATTERN (neste caso, cada linha no arquivo1) como sequências fixas e não expressões regulares:

  -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.)

Também escrevi um script PERL com mais algumas opções:

$ 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
    
por 09.12.2012 / 14:50