[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [shell-script] Desempenho ao checar se string existe em arquivo de t
From: |
Ronaldo Ferreira de Lima |
Subject: |
Re: [shell-script] Desempenho ao checar se string existe em arquivo de texto |
Date: |
Wed, 24 Dec 2014 15:04:01 -0200 |
User-agent: |
mutt-ng/devel-r804 (Linux) |
On Tue, Dec 23, 2014 at 11:36:39PM -0200, Fernando Mercês address@hidden
[shell-script] wrote:
> Amigos,
> Num script que acabei de fazer [1] tenho um arquivo de texto que é uma lista
> de
> nomes de usuário (um por linha). E quero checar se eles existem no sistema.
> Fiz
> deste jeito:
>
> while IFS= read i; do
> grep -qm1 "^$i:" /etc/passwd && echo "$i matches with an existent user.
> Be careful!"
> done < "$outfile"
>
> Mas este "$outfile" é muito grande. Milhares de linhas e demora um pouco.
> Alguma ideia pra otimizar?
Sim, algumas:
a. associative arrays:
declare -A username
while IFS=$':\n' read user last; do
let "username[$user] += 1"
(( username[$user] > 1 )) && echo $user
done < <(cat /etc/passwd usernames.txt)
b. awk:
awk -F: 'a[$1]++' /etc/passwd usernames.txt
c. grep -f + cut:
grep -x -f <(cut -d: -f1 /etc/passwd) usernames.txt
d. sort+cut+uniq:
sort <(cut -d: -f1 /etc/passwd) usernames.txt|uniq -d
Nos meus testes, 'usernames.txt' é o equivalente ao seu $outfile e é um
arquivo com 1k usernames e apenas 1 existente no /etc/passwd. Assumi
também que não existem duplicidade dentro do $outfile.
Realizei um benchmark com uma ferramenta desenvolvida a princípio para
testar código Perl mas que produz um relatório bem legível:
Benchmarking a => sub { system q(bash associative_array.sh 2&>/dev/null) }, b
=> sub { system q(bash awk.sh &>/dev/null) }, c => sub { system q(bash
grep-f+cut.sh &>/dev/null) }, d => sub { system q(bash sort+cut+uniq.sh
&>/dev/null) } ...
Benchmark: timing 1000 iterations of a, b, c, d...
a: 37 wallclock secs ( 0.01 usr 0.13 sys + 32.94 cusr 2.59 csys =
35.67 CPU) @ 28.03/s (n=1000)
b: 7 wallclock secs ( 0.02 usr 0.11 sys + 4.78 cusr 1.29 csys =
6.20 CPU) @ 161.29/s (n=1000)
c: 8 wallclock secs ( 0.01 usr 0.11 sys + 4.91 cusr 1.13 csys =
6.16 CPU) @ 162.34/s (n=1000)
d: 6 wallclock secs ( 0.01 usr 0.11 sys + 3.50 cusr 1.53 csys =
5.15 CPU) @ 194.17/s (n=1000)
O campeão aqui foi o 'sort+cut+uniq'. Não consegui incluir o seu código
nos testes porque demorava muito a conclusão na minha máquina. Ele fica
abaixo de 1/s e fica muito aquém dos outros exemplos.
Como última observação, dependendo do tamanho do /etc/passwd, do
$outfile e da quantidade duplicatas, esses valores podem mudar.
> Grato e feliz natal! :)
> [1] https://gist.github.com/merces/0a4d2272d79d00cc0fe1
> Att,
>
> Fernando Mercês
> Linux Registered User #432779
> www.mentebinaria.com.br
> ------------------------------------
> "Ninguém pode ser escravo de sua identidade; quando surge uma possibilidade de
> mudança é preciso mudar". (Elliot Gould)
[]'s
--
"Não manejo bem as palavras
Mas manipulo bem as strings."
------------------------------
http://tecnoveneno.blogspot.com