A primeira solução que tentei (existe uma alternativa mais rápida abaixo) é semelhante ao apresentado pelo @steeldriver. No entanto, os valores no arquivo2 precisam ter um ponto de partida para evitar que uma linha como a.bb.com
corresponda em cc.aa.bb.com
. As correspondências devem ter um ponto como um delimitador. Fazendo isso em quatro etapas:
n=100
echo "step1 ==============="
time head -n $n file2 | sort | tee file222 | sed 's/\./\./g;s/^/\./;s/$/$/' >file22
echo "step2 ==============="
time sed 's/^/./' file1 | head -n $n > file11
echo "step3 ==============="
time grep -oEf file22 file11 | sort -u | sed 's/^\.//' >file33
echo "step4 ==============="
time comm -13 file33 file222 > fileout
Mas o tempo aumenta como o quadrado de n
, é bastante rápido por menos que 1000
linhas (ambos os arquivos). Mas cresce para a ordem de 475
dias (mais de um ano) para 1 milhão de linhas. Claramente não é uma solução viável.
Opção b
Uma opção não tão intuitiva é expandir o arquivo1 para todos os seus constituintes.
Um processo semelhante ao expandir aa.ff.bb.com
para:
aa.ff.bb.com
ff.bb.com
bb.com
com
Depois, depois de remover linhas repetidas neste arquivo, encontre todas as linhas que existem apenas no arquivo (classificado )2.
A etapa para classificar (e remover repetições) usa a maior parte do tempo, mas na ordem de 8 segundos para um arquivo de linhas de 1 milhão (único), é bastante razoável.
Todo o processo (incluindo a geração de arquivos fonte) é:
#!/bin/bash
TIMEFORMAT='%R %U %S'
echo $'bb.com\na.com\n123.com' >file2
printf '%s\n' {a..z}{a..m}.{a..z}{a..m}.{com,net,dot} >>file2
echo $'aa.bb.com\naa.ff.bb.com\naa.bb.cc.com\na.com' >file1
printf '%s\n' {h..k}.{e..z}{a..m}.{e..z}{a..m}.{com,net,dot} >>file1
echo "file2 has $(wc -l <file2) lines"
echo "file1 has $(wc -l <file1) lines"
n=10000000
time sed -n 'p;:1;s/[^.]*\.//p;t1' file1 >file1b1
echo "file1b1 has $(wc -l <file1b1) lines"
time sort -u file1b1 | head -n $n >file1b2
echo "file1b2 has $(wc -l <file1b2) lines"
time sort -u file2 | head -n $n >file2b2
time comm -13 file1b2 file2b2 >fileout
Isso imprime os resultados:
file2 has 342735 lines
file1 has 981556 lines
4.353 4.248 0.096
file1b1 has 3926221 lines
8.649 15.024 0.488
file1b2 has 1227809 lines
0.618 0.908 0.112
1.011 0.968 0.032
Na ordem de 15 segundos.