Com bash
, zsh
e algumas implementações de ksh
:
comm -12 <(tr -s '[:space:]' '[\n*]' < a.txt | sort -u) \
<(tr -s '[:space:]' '[\n*]' < b.txt | sort -u)
Lá, word é uma sequência de caracteres sem espaçamento (cuidado com o GNU tr
, que não funciona com caracteres de espaçamento de bytes múltiplos).
comm
localiza as linhas comuns entre dois arquivos classificados. Sem opções, imprime 3 colunas: as linhas somente no arquivo1, as linhas somente no arquivo2 e as linhas comuns a ambos. Você adiciona -1
, -2
, -3
para remover as colunas correspondentes da saída. Portanto, comm -12
apenas deixa a terceira coluna (as linhas comuns).
tr -s '[:space:]' '[\n*]'
tr analisa qualquer equação s de caracteres da classe space
em novas linhas, para colocar cada palavra em sua própria linha .
sort -u
classifica e remove as duplicatas da saída de tr
.
A substituição de processo <(...)
canaliza as saídas dos comandos tr|sort
para comm
.
com zsh
:
w1=($(<a.txt)) w2=($(<b.txt))
print -rl -- ${(u)${w1:*w2}}
Lá, palavra é uma sequência de caracteres diferente de espaço, tabulação, nul e nova linha (com o valor padrão de $IFS
).
$(<a.txt)
é uma versão otimizada de $(cat a.txt)
, em que zsh
lê o conteúdo do arquivo sozinho sem invocar cat
, pois ele não é citado, ele passa por uma divisão de palavras (mas não globbing contrário a outros shells) .
Portanto, w1
e w2
são matrizes contendo todas as palavras em a.txt
e b.txt
.
${w1:*w2}
é um operador zsh que fornece a interseção de duas matrizes (os elementos comuns a ambos). (u)
é um sinalizador de expansão de parâmetro que retém elementos exclusivos (remove duplicados).
print -rl
imprime cada argumento um por linha.