shell-script-pt
[Top][All Lists]
Advanced

[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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]