Como extrair texto incomum insensível a maiúsculas e minúsculas de dois arquivos?

4

Estou tentando extrair texto incomum do arquivo e tentei fazer isso:

awk 'FNR==NR {a[$0]++; next} !a[$0]' 1.txt 2.txt
http://PQR.com
http://example.com

Aqui estão os arquivos de entrada:

File: 1.txt
http://google.com
http://GOOGLE.com
http://example1.com
http://seperate.com
http://pqr.com
File: 2.txt
http://PQR.com
http://example.com
http://google.com

Como você pode ver, http://pqr.com está disponível no arquivo 1.txt e http://PQR.com in 2.txt . e a exibição do resultado http://PQR.com , que é comum em ambos os arquivos. Portanto, como posso mostrar apenas o texto incomum (não dependendo dos casos do texto)?

    
por Jaffer Wilson 06.02.2017 / 09:31

3 respostas

7

Como você já está usando awk , use tolower para diminuir as linhas:

awk 'FNR==NR {a[tolower($0)]++; next} !a[tolower($0)]' foo bar

No entanto, isso só imprime linhas em bar que não estavam em foo .

Compare com:

$ sort -f bar foo | uniq -iu
http://example.com
http://example1.com
http://seperate.com

Com awk , você também precisa imprimir todas as linhas que foram vistas apenas uma vez:

$ awk '{a[tolower($0)]++} END {for (i in a) if (a[i] == 1) print i}' foo bar
http://seperate.com
http://example.com
http://example1.com
    
por muru 06.02.2017 / 09:50
4

Este é um trabalho bem simples para grep :

grep -viFf file2.txt file1.txt
  • -v mostra as linhas que não correspondem a
  • -i habilita a insensibilidade a maiúsculas e minúsculas
  • -F faz padrões literais
  • -f file1.txt lê padrões para corresponder de file1.txt , linha por linha

Exemplo:

% cat file1.txt 
http://google.com
http://GOOGLE.com
http://example1.com
http://seperate.com
http://pqr.com

% cat file2.txt 
http://PQR.com
http://example.com
http://google.com

% grep -viFf file2.txt file1.txt
http://example1.com
http://seperate.com
    
por heemayl 06.02.2017 / 09:50
4

Aqui está uma solução Python usando uma implementação de conjunto eficiente para um bom desempenho O ( n + m ) (com n e m sendo os tamanhos dos dois arquivos de entrada).

Código

#!/usr/bin/python3
import sys

with open(sys.argv[1]) as A_file:
    A = frozenset(map(str.casefold, map(str.rstrip, A_file)))

with open(sys.argv[2]) as B_file:
    B = map(str.rstrip, B_file))
    B_minus_A = filter(lambda s: s.casefold() not in A, B)
    print(*B_minus_A, sep='\n')

Exemplo de uso

python3 casefold-difference.py 1.txt 2.txt

Explicação

  • O programa usa casefold para comparação de strings, mas retorna as linhas como eles aparecem em 2.txt . A dobra de maiúsculas e minúsculas é a maneira recomendada de fazer uma comparação sem distinção entre maiúsculas e minúsculas da linguagem natural. Se não é isso que você quer (já que URLs não são realmente linguagem natural) você pode substituí-lo por lower .

  • Se 2.txt tiver uma quantidade enorme de linhas (que não aparecem em 1.txt ), a criação da lista de argumentos variadic na última instrução pode consumir bastante memória e talvez seja melhor substituir com um loop como este:

    for item in B_minus_A:
        print(item)
    
por David Foerster 06.02.2017 / 12:56