Estou usando o Solaris 10 e, portanto, as opções grep envolvendo -f não funcionam.
Eu tenho dois arquivos separados por canal:
file1:
abc|123|BNY|apple|
cab|234|cyx|orange|
def|kumar|pki|bird|
arquivo 2:
abc|123|
kumar|pki|
cab|234
Gostaria de comparar as duas primeiras colunas do arquivo2 com o arquivo1 (pesquise todo o conteúdo do arquivo1 nas duas primeiras colunas) se elas corresponderem à impressão da linha correspondente do arquivo1. Em seguida, procure a segunda linha do arquivo 2 e assim por diante.
Saída esperada:
abc|123|BNY|apple|
cab|234|cyx|orange|
Os arquivos que eu tenho são enormes, contendo cerca de 400.000 linhas, então eu gostaria de acelerar a execução.
shell-script
text-processing
perl
user68365
fonte
fonte
grep
, está abaixo/usr/sfw/bin/ggrep
. stackoverflow.com/questions/15259882/…Respostas:
É para isso que o awk foi projetado:
Explicação
-F'|'
: define o separador de campo para|
.NR==FNR
: NR é o número da linha de entrada atual e FNR o número da linha do arquivo atual. Os dois serão iguais apenas enquanto o 1º arquivo estiver sendo lido.c[$1$2]++; next
: se esse for o 1º arquivo, salve os dois primeiros campos nac
matriz. Em seguida, pule para a próxima linha para que isso seja aplicado apenas no 1º arquivo.c[$1$2]>0
: o bloco else será executado somente se este for o segundo arquivo, portanto verificamos se os campos 1 e 2 deste arquivo já foram vistos (c[$1$2]>0
) e, se foram, imprimimos a linha. Emawk
, a ação padrão é imprimir a linha e, sec[$1$2]>0
for verdadeira, a linha será impressa.Como alternativa, desde que você marcou com Perl:
Explicação
A primeira linha será aberta
file2
, leia tudo até a segunda|
(.+?\|[^|]+
) e salve ($&
o resultado do último operador de correspondência) no%k
hash.A segunda linha processa o arquivo1, usa o mesmo regex para extrair as primeiras duas colunas e imprimir a linha se essas colunas estiverem definidas no
%k
hash.Ambas as abordagens acima precisarão conter as 2 primeiras colunas do arquivo2 na memória. Isso não deve ser um problema se você tiver apenas algumas centenas de milhares de linhas, mas se for, você poderia fazer algo como
Mas isso será mais lento.
fonte
file2
na memória?awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0'
é a versão mais curta.file2
linhas duplicadas?eu acho que
é o que você está procurando. Deve ser eficiente, mas não tenho certeza de que será tão preciso quanto você deseja. Se
abc|123
(por exemplo) for encontrado em uma linha emfile1
colunas diferentes, essa linha também será impressa. Se você pode garantir que isso nunca aconteça, a linha acima deve funcionar.fonte
Se você gostaria de pensar o problema no SQL da mesma maneira, definitivamente deveria tentar uma ferramenta chamada ' q ':
É mais claro e fácil de entender se você estiver familiarizado com a consulta SQL.
fonte
fonte