function are_all_there {
local num_diff=$(comm -3 <(cut -d'|' -f3 "$1" | sort) <(sort "$2") | wc -l)
(( num_diff == 0 )) && return 1 || return 2
}
Eu tenho 2 arquivos ..
arquivo1:
abc|123|check
def|456|map
ijk|789|globe
lmn|101112|equator
arquivo2:
check
map
equator
globe
A função AWK deve comparar a 3ª coluna (depois de cortar a 3ª coluna e a classificação) do arquivo1 comparando com o conteúdo classificado como arquivo2
function are_all_there {
local num_diff=$(comm -3 <(cut -d'|' -f3 "$1" | sort) <(sort "$2") | wc -l)
(( num_diff == 0 )) && return 1 || return 2
}
Com base nos seus comentários, parece que awk
não é sua única opção. então aqui está um método não-awk.
Você não menciona a necessidade de uma comparação exclusiva na pergunta, mas usou uniq
no exemplo em seu comentário. Se você não precisa de uma correspondência exclusiva , basta remover a opção -u
da classificação. (testado em bash
)
.
(($(comm -3 <( cut -d'|' -f3 file1 | sort -u ) \
<( sort -u file2 ) | wc -l))) && echo 2 - not all match ||
echo 1 - all match
Ou usando awk
para a comparação final - com um pouco de ajuda de paste
.
paste <( cut -d'|' -f3 file1 | sort -u ) \
<( sort -u file2 ) |
awk '$1!=$2{m=2; exit}
END{ if(m == 2){print "2 - not all match"; exit;}
print "1 - all match";}'
Ou, awk
comparação de dois arquivos de entrada
awk '{if(NR == FNR){a[NR]=$1}
else{ if($1 != a[NR]){m=2; exit}}}
END{ if(m == 2){print "2 - not all match"; exit;}
print "1 - all match";}' \
<( cut -d'|' -f3 file1 | sort -u ) \
<( sort -u file2 ) |
Divertido CS responde! Na verdade, não temos que classificar nada, porque essa é uma comparação de conjunto pura.
Os arquivos de entrada são representação de um conjunto no qual os elementos são pares. Por exemplo, se a linha foo
ocorrer 3 vezes em file1
, isso representa o elemento < foo
, 3 & gt ;. Se file2
contiver foo
3 vezes, isso significa que ambos os conjuntos contêm esse elemento. Se file2
não contiver foo
ou contiver um número diferente de repetições de foo
, então ele representa um conjunto que não contém < foo
, 3 >.
Além disso, observe que um conjunto de pares como < foo
, 3 > pode ser representado por um hash que mapeia a chave foo
para 3.
Macro awp do TXr Lisp:
(awk (:begin (set fs "|"))
(:let (h1 (hash :equal-based)) (h2 (hash :equal-based)))
((= arg 1) (inc [h1 [f 2] 0]))
((= arg 2) (inc [h2 rec 0]))
(:end (exit (equal h1 h2))))
Isso produz um status de finalização bem-sucedido se os arquivos forem iguais na forma necessária, caso contrário, um status com falha:
$ txr comp.tl file1 file2 $ echo $? 0 $ echo map >> file2 $ txr comp.tl file1 file2 $ echo $? 1
Se quisermos complicar as coisas para o programa de chamada fazendo com que ele analise a saída "1" ou "2", isso pode ser feito alterando a regra :end
:
(:end (prn (if (equal h1 h2) "1" "2")))
Aqui está como as coisas parecem no awk normal. A principal diferença é que temos uma sintaxe concisa, na qual não precisamos definir nenhuma variável a que nos referimos; por outro lado, temos que escrever um par de loops para comparar dois arrays associativos e gerar nossa própria variável arg
para rastrear qual arquivo estamos processando. (GNU Awk tem o ARGIND
para este propósito.)
BEGIN { FS = "|" }
FNR == 1 { arg++ }
arg == 1 { h1[$3]++; }
arg == 2 { h2[$0]++; }
END { same = 1
for (i in h1)
if (h1[i] != h2[i]) {
same = 0
break
}
if (same)
for (i in h2)
if (h2[i] != h1[i]) {
same = 0
break
}
print same ? "1" : "2"; }
Tags text-processing awk