Archive for the ‘bash’ Tag

Variáveis em subshells

Recentemente enfrentei alguma dificuldade com a contabilização de contadores em shell script durante o processamento de arquivos texto. Para fins didáticos, ilustrarei com um exemplo simples. Imaginem que gostaríamos de saber quantos usuários têm como grupo principal o users. Poderíamos resolver o problema como no exemplo a seguir:

GRUPO=100   # users
CONTADOR=0
cat /etc/passwd | while read VALORES
do
   # verifica se grupo do usuario eh o grupo que deve ser contabilizado
   if [ `echo ${VALORES} | cut -d":" -f4` == ${GRUPO} ]
   then
      let CONTADOR++
   fi
done
echo ${CONTADOR}

Sei que existem maneiras mais simples de resolver o problema, mas lembro que é um exemplo didático, com o objetivo de ilustrar a dificuldade que encontrei.

Bom este era o meu raciocínio antes de dar-me conta da questão do subshell criado pelo pipe (|) que adicionei na minha lógica (vejam detalhes sobre o escopo de variáveis em subshells). Quando se faz uso de subshells em progração de shell script, todas as variáveis criadas neste contexto somente são válidas entre o “do” e o “done” (para o caso do exemplo citado).

E qual a solução para o problema então? Bom, como em toda programação, podem existir várias! A primeira tentativa seria contornar o uso de subshells. Para o exemplo citado, seria bastante simples:

GRUPO=100   # users
echo "Número de usuários no grupo ${GRUPO}: `cat /etc/passwd | cut -d":" -f4` | grep ${GRUPO} | wc -l`"

Mas nem sempre a solução pode descartar o uso de subshells. O que fazer então? Uma outra alternativa seria o uso de um arquivo temporário como acumulador:

GRUPO=100   # users
TMP="/tmp/contador.tmp"
echo 0 > ${TMP}
cat /etc/passwd | while read VALORES
do
   # verifica se grupo do usuario eh o grupo que deve ser contabilizado
   if [ `echo ${VALORES} | cut -d":" -f4` == ${GRUPO} ]
   then
      CONTADOR=`cat ${TMP}`
      let CONTADOR++
      echo ${CONTADOR} > ${TMP}
   fi
done
echo `cat ${TMP}`
rm ${TMP}

Pode não ser uma solução tão elegante, mas é funcional! Se desejarem adicionar mais sugestões, por favor, colaborem.