Desenvolvimento

6 dez, 2016

Shell: sorteando coisas como um dev

Publicidade

Já participou de algum tipo de sorteio em eventos de desenvolvimento? Viu o random.org sendo usado ou algo parecido? Já pensou na shell como IDE e usá-la pra isso?

Precisamos de algumas coisas pra fazer isso acontecer:

  1. Uma lista (arquivo) a ser sorteada. Uma pessoa por linha.
  2. Um número randômico.
  3. Uma linha específica do arquivo.

O número randômico precisa de um limite, que é o total de linhas no arquivo (/tmp/file):

$ wc -l /tmp/file.txt
    312 /tmp/file.txt
$ wc -l /tmp/file.txt | awk '{print $1}'
312

O wc imprime o número de linhas e o nome do arquivo, por isso usamos o awk pra retornar só a primeira parte do output do wc.

$ echo $RANDOM
31938
$ upper_limit=$((312+1))
$ lower_limit=1
$ echo $(( ($RANDOM % $upper_limit) + $lower_limit ))
198

O resto da divisão entre $RANDOM e o total de linhas no arquivo garante que o maior número seja o total de linhas no arquivo. O limite inferior garante que 0 (zero) não ocorra, já que a primeira linha do arquivo é a 1 (um). Se você está se perguntando das operações entre dois parênteses, elas são a expansão aritmética da shell.

$ random_line=198
$ awk "NR==${random_line}" /tmp/file.txt
john@doe.com

A variável NR (do awk) é o número de registros interpretados até agora. Por padrão, um registro é uma linha, então nosso programa awk está avaliando se o registro atual é o número randômico que passamos; caso sim, ele imprime a linha.

Se juntarmos tudo isso num script, nos preocupando com a leitura e manutenção dele:

#!/usr/bin/env sh
# Prints a random line from a file

lines_on() {
    file=$1
    wc -l $file | awk '{print $1}'
}

random_until() {
    max=$1
    min=1
    echo $(( ($RANDOM % $max) + $min ))
}

print_line_in_file() {
    file=$1
    line=$2
    awk "NR==${line}" $file
}

if [ -z "$1" ]
then
    echo "Usage: $0 <file>"
    exit 2
fi

# Here be dragons
print_line_in_file $1 $(random_until $(lines_on $1))

O importante não é lembrar que ele existe, mas transformar o uso dos comandos acima em memória muscular. Acredite, todos eles são úteis no dia a dia. O awk, então, é uma linguagem inteira.

Quer uma lição de casa? Que tal evitar repetir pessoas já sorteadas?