awk
pode fazer todos os trabalhos de read
, cut
, grep
e bc
aqui:
awk -F': *' '
$1 == "MemTotal" {t = $2}
$1 == "MemFree" {f = $2}
END {printf "%.1f%%\n", (t - f) * 100 / t}' /proc/meminfo
Tenha em atenção que nem todas as implementações awk
produzirão 40,5% em vez de 40,5 nas localidades onde a vírgula é usada como base decimal (GNU awk
apenas o faz no modo POSIX como quando $POSIXLY_CORRECT
está no ambiente ). Use LC_ALL=C awk...
para forçar a raiz decimal a ponto / período.
Altere %.1f
para %.0f
se você não quiser uma parte decimal. Isso arredondará para o inteiro mais próximo . Use %d
se você quiser truncar a parte decimal (obtenha 99% ao invés de 100% para 99.999).
Seu read t f <<< 'grep -E 'Mem(Total|Free)' /proc/meminfo |awk '{print $2}''
teria funcionado em versões mais antigas de bash
, assumindo uma $IFS
não modificada.
Em cmd <<< 'code'
, bash
usado para dividir a saída de code
nos caracteres de $IFS
(que, por padrão, inclui nova linha) e uni-los ao primeiro caractere de $IFS
(por padrão espaço) antes alimentando como stdin ao comando. Portanto, no seu caso, essas duas linhas de saída de awk
acabariam sendo alimentadas como duas palavras em uma linha conforme esperado por read t f
. Esse comportamento surpreendente (e também diferente da implementação original em zsh
) foi corrigido no bash-4.4.
Em bash-4.4
e acima, você precisaria de { read t; read f; } <<< "$(awk...)"
(aqui, adicionando aspas em torno de $(...)
, para que também funcione no bash-4.3 e antes, ainda assumindo o valor padrão de $IFS
).