Introdução
Comandos pequenos do Linux se tornam muito mais úteis quando o shell coordena a execução entre eles. Um comando informa se foi concluído com sucesso ou falhou por meio de um status de saída; os operadores de sequência decidem o que será executado em seguida; um pipe conecta a saída padrão de um comando à entrada padrão de outro.
Você aprenderá esses conceitos em camadas e, depois, usará grep, cut, wc, sort e uniq para transformar um pequeno conjunto de dados de eventos de serviço. Laboratórios posteriores de processamento de texto aprofundarão esses filtros. Por isso, o foco aqui é entender como os dados e as decisões passam de um comando para outro.
Observe o status de saída dos comandos
Nesta etapa, você relacionará o comportamento visível dos comandos ao status numérico que o shell registra.
Um status de saída 0 significa sucesso; um valor diferente de zero significa que o comando não conseguiu concluir a operação solicitada. Execute um teste de arquivo bem-sucedido e, imediatamente depois, exiba $?, que contém o status mais recente:
cd /home/labex/project/pipeline-lab
test -f events.csv
echo $?
A saída será 0. Agora teste um arquivo inexistente:
test -f missing.csv
echo $?
O status será diferente de zero. Leia $? imediatamente, porque cada comando executado depois substitui esse valor.
Crie uma verificação estável usando uma instrução if. Você estudará scripts completos de shell mais adiante; aqui, a instrução apenas converte o status em texto:
if test -f events.csv; then echo "events.csv is ready"; else echo "events.csv is missing"; fi > status-result.txt
cat status-result.txt
Controle qual comando será executado em seguida
Nesta etapa, você comparará operadores de comandos incondicionais e condicionais.
Um ponto e vírgula executa o próximo comando independentemente do resultado do comando anterior:
false; echo "semicolon continues"
&& executa o comando à direita somente após um resultado bem-sucedido:
test -f events.csv && echo "input found"
test -f missing.csv && echo "you should not see this"
|| executa o comando à direita somente após uma falha:
test -f missing.csv || echo "input missing"
Esses operadores podem expressar uma pequena decisão de sucesso ou falha. Copie o conjunto de dados somente se ele existir; caso contrário, exiba um erro:
test -f events.csv && cp events.csv working.csv || echo "Copy failed"
Verifique se a cópia protegida é igual à origem:
cmp events.csv working.csv && echo "guarded copy matches" > sequence-result.txt
cat sequence-result.txt
Para lógicas complexas, prefira uma instrução if legível; cadeias longas com && e || podem se tornar ambíguas.
Envie a saída por um pipeline
Nesta etapa, você conectará comandos com | e observará como cada etapa reduz o fluxo de dados.
O comando à esquerda envia a saída padrão para o pipe; o comando à direita lê esses dados como entrada padrão. Selecione apenas os registros ERROR:
cd /home/labex/project/pipeline-lab
cat events.csv | grep ',ERROR,'
grep pode ler um arquivo diretamente, portanto esta forma mais curta produz o mesmo resultado:
grep ',ERROR,' events.csv
Adicione wc -l para contar as linhas correspondentes:
grep ',ERROR,' events.csv | wc -l
Salve tanto o fluxo filtrado quanto a contagem. tee duplica sua entrada padrão: grava uma cópia em error-events.csv e envia a outra cópia adiante pela saída padrão. Por isso, o wc -l final conta exatamente as linhas salvas:
grep ',ERROR,' events.csv | tee error-events.csv | wc -l > error-count.txt
cat error-events.csv
cat error-count.txt
Inspecione os dois arquivos depois de executar o pipeline. error-events.csv contém os registros correspondentes, enquanto error-count.txt contém a quantidade desses registros.
Extraia campos com cut
Nesta etapa, você tratará cada linha CSV como um conjunto de campos separados por delimitadores.
cut -d, -f1 usa a vírgula como delimitador e exibe o campo 1, que contém o nome do serviço:
cd /home/labex/project/pipeline-lab
cut -d, -f1 events.csv
Exiba juntos os campos de serviço e severidade:
cut -d, -f1,2 events.csv
Combine filtragem e extração para listar apenas os serviços que produziram avisos:
grep ',WARN,' events.csv | cut -d, -f1
Salve este resultado intermediário:
grep ',WARN,' events.csv | cut -d, -f1 > warning-services.txt
cat warning-services.txt
cut funciona bem para registros simples cujo delimitador nunca aparece dentro de um campo. Formatos mais complexos podem exigir awk ou uma ferramenta que reconheça o formato.
Classifique e conte valores repetidos
Nesta etapa, você criará um pipeline completo de frequência e entenderá por que a classificação precisa ocorrer antes de uniq.
uniq combina apenas linhas iguais adjacentes. Primeiro extraia os nomes dos serviços e, depois, classifique-os para que os valores idênticos fiquem lado a lado:
cd /home/labex/project/pipeline-lab
cut -d, -f1 events.csv | sort
Adicione uniq -c para contar cada sequência de nomes iguais:
cut -d, -f1 events.csv | sort | uniq -c
Classifique as contagens numericamente em ordem decrescente. sort -k1,1nr usa o primeiro campo como uma chave numérica em ordem inversa:
cut -d, -f1 events.csv | sort | uniq -c | sort -k1,1nr
Salve o relatório final:
cut -d, -f1 events.csv | sort | uniq -c | sort -k1,1nr > service-frequency.txt
cat service-frequency.txt
Leia este pipeline da esquerda para a direita: extrair → classificar → contar duplicatas adjacentes → ordenar as contagens.
Resumo
Você usou o status de saída como sinal de sucesso do shell, controlou a execução com ;, && e || e criou pipelines com etapas bem definidas. Depois, filtrou registros, extraiu campos, contou linhas, classificou valores e contou duplicatas — exatamente o vocabulário necessário para o próximo Challenge de pipeline de dados.



