Se você quiser exibir duas coisas lado a lado, pode usar printf para impressão formatada.
#!/bin/bash
sort "$1" | uniq | while read line; do
md5=$(md5sum <<< "$line")
printf "%s %s\n" "$md5" "$line"
done
times
Eu tenho o seguinte script:
#!/usr/bin/env bash
# Script to generate MD5 hash for each line.
[ $# -eq 0 ] && { echo "Usage: $0 file"; exit 1; }
file=$1
shopt -s expand_aliases
alias calc_md5='while read -r line; do md5sum <<<$line; done'
paste <(sort "$file" | uniq | calc_md5) <(sort "$file" | uniq)
times
que imprime a soma de verificação MD5 para cada linha, lado a lado, exatamente como eu preciso. Por exemplo:
$ ./md5_lines.sh file.dat
5c2ce561e1e263695dbd267271b86fb8 - line 1
83e7cfc83e3d1f45a48d6a2d32b84d69 - line 2
0f2d633163ca585e5fc47a510e60f1ff - line 3
73bb3632fc91e9d1e1f7f0659da7ec5c - line 4
O problema com o script acima é que ele precisa ler e analisar o arquivo duas vezes, para cada coluna / fluxo. Idealmente, gostaria de classificar e tornar todas as linhas exclusivas e usá-las como entrada apenas uma vez.
Como posso converter o script acima para analisar o arquivo apenas uma vez ( sort
& uniq
), então redirecionar a saída para dois fluxos diferentes e exibir linhas lado a lado, para que ele possa funcionar mais rápido para o arquivos maiores?
Aqui está minha outra tentativa:
tee >(calc_md5) >(cat -) \
< <(sort "$file" | uniq) \
>/dev/null
times
mas imprime os fluxos separadamente (não lado a lado).
Idealmente, gostaria de usar paste
, da mesma forma que tee
, mas isso me dá o erro:
$ paste >(cat -) >(cat -) </etc/hosts
paste: /dev/fd/63: Permission denied
Se você quiser exibir duas coisas lado a lado, pode usar printf para impressão formatada.
#!/bin/bash
sort "$1" | uniq | while read line; do
md5=$(md5sum <<< "$line")
printf "%s %s\n" "$md5" "$line"
done
times
Um par de abordagens Perl:
Use o Perl para obter o md5sum
$ perl -ne 'BEGIN{
use Digest::MD5 qw(md5_hex)
}
$k{$_}=md5_hex("$_");
END{
print "$k{$_} - $_" for sort keys(%k)
}' file
5c2ce561e1e263695dbd267271b86fb8 - line 1
83e7cfc83e3d1f45a48d6a2d32b84d69 - line 2
0f2d633163ca585e5fc47a510e60f1ff - line 3
73bb3632fc91e9d1e1f7f0659da7ec5c - line 4
d82912361d84a675530f5e32aa6eeda1 - line 5
E sim, este é um folheto:
perl -ne 'BEGIN{use Digest::MD5 qw(md5_hex)} $k{$_}=md5_hex("$_"); END{print "$k{$_} - $_" for sort keys(%k)}' file
Isso deve ser muito mais rápido do que fazer esse tipo de processamento no shell.
Use uma chamada de sistema
$ perl -lne 'chomp($md='md5sum <<<"$_"'); print "$md $_" if !$seen{$_}++' file
83e7cfc83e3d1f45a48d6a2d32b84d69 - line 2
0f2d633163ca585e5fc47a510e60f1ff - line 3
d82912361d84a675530f5e32aa6eeda1 - line 5
73bb3632fc91e9d1e1f7f0659da7ec5c - line 4
5c2ce561e1e263695dbd267271b86fb8 - line 1
Ir para um loop while read
tem muitos dos problemas mencionados em Por que usar um loop de shell para processar texto é considerado uma prática ruim?
Aqui, eu usaria perl
:
sort -u < "$file" | perl -MDigest::MD5=md5_hex -lpe '
$_ = md5_hex($_) . " - " . $_'
Sua pergunta mais geral se parece com uma duplicata ou uma variação de tee + cat: use uma saída várias vezes e, em seguida, concatene os resultados
Note que não é porque duas linhas ordenam o mesmo (significando sort -u
retém apenas uma) que elas serão idênticas e terão a mesma soma de verificação MD5. Você pode querer usar LC_ALL=C sort -u
para ordenar e unicar para ser baseado em uma comparação byte-a-byte ao invés de strcoll()
(também cuidado algumas implementações de sort
poderiam bloquear na entrada de texto que noC
% locale ainda incluiria linhas longas demais, linhas não delimitadas ou linhas contendo caracteres NUL).