Combinando e armazenando e retornando informações para entrada padrão

0

Então eu estou realmente preso aqui. Eu tenho alguns arquivos com milhões de linhas de dados neles formatados da seguinte forma:

username|process name|process time (in minutes)

Existem cerca de 3,4 milhões de linhas deste material. Agora, a tarefa que tenho em mãos é fazer um roteiro para eu mesmo examinar todos esses dados muito rapidamente.

Então, basicamente, eu quero inserir um nome de usuário a partir da linha de comando, extrair todas as linhas de dados com esse nome de usuário, resumi-las e, em seguida, exibi-las. Significado como o tempo total do processo para esse usuário, bem como o número total de processos para esse usuário.

Isto é o que eu tenho até agora e não é muito

tput cup 19 10
read -p "Please Enter a UserName: " uname

Isso é tudo que tenho. Alguém tem uma ideia de como eu posso fazer isso?

    
por user169644 10.05.2016 / 07:05

1 resposta

4

Vamos considerar isso como um arquivo de entrada de amostra:

$ cat file
jim|process1|23
bob|process2|5
jim|process3|7

Usando o awk

Agora, vamos criar este script de shell:

$ cat script.sh
#!/bin/sh
read -p "Please Enter a UserName: " uname
awk -v n="$uname" -F\| '$1==n{total+=$3} END{printf "Total for %s is %s minutes\n",n,total}' file

Como exemplo, vamos resumir o tempo usado por jim:

$ sh script.sh
Please Enter a UserName: jim
Total for jim is 30 minutes

Como funciona

O awk implicitamente percorre todas as linhas do arquivo de entrada. Esse script usa duas variáveis: n , que é o nome de usuário e total , que é o total de minutos em execução usado pelo usuário n .

  • -v n="$uname"

    Isso cria uma variável n do awk e atribui a ela o valor da variável uname da variável.

  • -F\|

    Isso diz ao awk para usar | como o separador de campo

  • $1==n{total+=$3}

    Sempre que o primeiro campo, $1 , corresponder ao nome do usuário, n , incrementamos o total total pela quantidade do terceiro campo, $3 .

  • END{printf "Total for %s is %s minutes\n",n,total}

    Quando terminamos de ler o arquivo, imprimimos o resultado.

Usando o shell

Como alternativa, podemos fazer o loop no shell:

$ cat script2.sh 
#!/bin/sh
read -p "Please Enter a UserName: " uname
while IFS=\| read -r name process minutes; do
    [ "$name" = "$uname" ] && total=$((total+minutes))
done <file
echo "Total for $uname is $total minutes"

Como demonstração:

$ sh script2.sh
Please Enter a UserName: jim
Total for jim is 30 minutes

Não cronometrei as duas abordagens, mas espero que awk seja muito mais rápido.

    
por 10.05.2016 / 07:19