perl -F, -lane '
exists $h{$F[0]} or $h[$h{$F[0]}=@h]=$_;
$h=$_; /,false$/ or $_=$h for $h[$h{$F[0]}];
END{ print for @h; }
' duplicates.file
Estruturas de dados:
- Hash
%h
cujas chaves são os primeiros campos (AAA, BBB, CCC, etc.) e os valores correspondentes são números informando a ordem em que as chaves foram encontradas. Assim, por exemplo, chave AAA = > 0, chave BBB = > 1, chave CCC = > 2.
- Matriz
@h
cujos elementos são linhas contidas na ordem de impressão. Então, se tanto true quanto false forem encontrados nos dados, então o valor false irá para o array. OTW, se houver um tipo de dado, isso estaria presente.
Outra maneira é usar o GNU sed:
sed -Ee '
G
/^([^,]*),(false|true)\n(.*\n)?,(\n|$)/ba
/^([^,]*)(,true)\n(.*\n)?,false(\n|$)/ba
/^([^,]*)(,false)\n((.*\n)?),true(\n|$)/{
s///;h;ba
}
s/([^\n]*)\n(.*)$/\n/;s/^\n*//
h;:a;$!d;g
' duplicates.file
FWIW, o código equivalente do POSIX para o código acima do GNU-sed é listado abaixo:
sed -e '
G
/^\([^,]*\),\(false\)\n\(.*\n\)\{0,1\},$/ba
/^\([^,]*\),\(false\)\n\(.*\n\)\{0,1\},\n/ba
/^\([^,]*\),\(true\)\n\(.*\n\)\{0,1\},$/ba
/^\([^,]*\),\(true\)\n\(.*\n\)\{0,1\},\n/ba
/^\([^,]*\),true\n\(.*\n\)\{0,1\},false$/ba
/^\([^,]*\),true\n\(.*\n\)\{0,1\},false\n/ba
/^\([^,]*\)\(,false\)\n\(\(.*\n\)\{0,1\}\),true$/{
s///
h
ba
}
/^\([^,]*\)\(,false\)\n\(\(.*\n\)\{0,1\}\),true\n/{
s//\n/
h
ba
}
y/\n_/_\n/
s/\([^_]*\)_\(.*\)$/_/;s/^_*//
y/\n_/_\n/
h;:a;$!d;g
' duplicates.file
Explicação
- Nesse método, armazenamos o resultado a ser finalmente impresso no espaço de armazenamento.
- Para cada linha lida, anexamos o espaço de espera ao espaço de padrão para exame da linha atual vis-à-vis o estado existente do espaço de espera.
- Agora, 5 coisas podem acontecer durante essa comparação:
- a) A linha atual corresponde a algum lugar na linha de espera & false: false.
- [ACTION] Como o mesmo estado falso é encontrado, não faça nada.
- b) A linha atual corresponde a algum lugar na linha de espera & verdade verdade.
- [ACTION] Como o mesmo estado verdadeiro é encontrado, não faça nada.
- c) A linha atual corresponde a algum lugar na linha de espera & verdadeiro falso.
- [ACTION] Como já existe um estado falso, não faça nada.
- d) A linha atual corresponde a algum lugar na linha de espera & falso verdadeiro.
- [ACTION] Isso envolve algum trabalho, na medida em que precisamos substituir a linha falsa exatamente na mesma posição em que o verdadeiro está localizado.
- e) A linha atual NÃO corresponde em nenhum lugar da linha de espera.
- [ACTION] Mova a linha atual até o final.
Resultados
AA,false
BB,false
CC,false
DD,true