Piping sed para grep parece não funcionar como esperado

3

Eu tenho 2 arquivos:

$ cat file1  
jim.smith  
john.doe  
bill.johnson  
alex.smith  

$ cat file2   
"1/26/2017 8:02:01 PM",Valid customer,jim.smith,NY,1485457321      
"1/30/2017 11:09:36 AM",New customer,tim.jones,CO,1485770976     
"1/30/2017 11:14:03 AM",New customer,john.doe,CA,1485771243  
"1/30/2017 11:13:53 AM",New customer,bill.smith,CA,1485771233  

Eu quero do arquivo2 todos os nomes que não existem no arquivo1.
O seguinte não funciona:

$ cut -d, -f 3 file2 | sed 's/"//g' | grep -v file1  
jim.smith  
tim.jones  
john.doe  
bill.smith  

Por que o pipe para grep -v não funciona neste caso?

    
por Jim 05.02.2017 / 19:24

4 respostas

11

Este é praticamente o último passo da minha resposta à sua pergunta anterior .

Sua solução funciona, se você adicionar -f na frente de file1 no grep :

$ cut -d, -f3 file2 | grep -v -f file1
tim.jones
bill.smith

Com o -f , grep procurará em file1 pelos padrões. Sem isso, ele simplesmente usará file1 como o padrão literal.

Você também pode querer usar -F , caso contrário, o ponto no padrão será interpretado como "qualquer caractere". E enquanto você está nisso, coloque -x também para que grep realize a correspondência em toda a linha (será útil se você tiver um joe.smith que não corresponda a joe.smiths ):

$ cut -d, -f3 file2 | grep -v -F -x -f file1

Isso requer, obviamente, que não haja espaços à direita no final das linhas em file1 (o que parece estar no texto da pergunta).

Observe que sed não é necessário, pois a saída de cut não contém " . Além disso, se você tivesse necessário para remover todos os " , então tr -d '"' teria sido uma ferramenta melhor.

    
por 05.02.2017 / 20:04
5

Tente isso. Nenhum código%. Requer GNU sed e diff .

diff --new-line-format="" --unchanged-line-format="" <(cut -f3 -d, file2|sort) <(sort file1)

Produz resultados:

bill.smith
tim.jones
    
por 05.02.2017 / 20:07
3

Isso deve funcionar:

$ pattern=$(cut -d, -f 3 file2)
$ grep -v -e "$pattern" file1  

No seu exemplo, o grep erra seu padrão. Além disso, o grep pode ler um arquivo ou stdin (por pipe), não ambos. Se o nome do arquivo não é dado, então o grep lê o stdin.

Além disso, isso também pode funcionar:

$ grep -v -f <(cut -d, -f3 file1) file2  

Desculpe, não foi testado.

    
por 05.02.2017 / 19:40
2

A resposta com grep -f é provavelmente a melhor, mas uma alternativa um pouco estilosa é:

% cut -d, -f3 file2 >names2
% cat file1 file1 names2 | sort | uniq -u
bill.smith
tim.jones
%

Isso, é claro, requer um arquivo temporário extra (ou diversão e jogos com descritores de arquivos), e eu não gostaria de testá-lo com arquivos grandes.

Eu mencionei isso apenas porque, para tarefas que envolvem a correspondência entre arquivos, sort plus uniq é um par de ferramentas inesperadamente versátil e talvez subestimado. Para tarefas rápidas, elas podem fornecer um caminho pouco necessário para um resultado.

    
por 06.02.2017 / 11:38