Como detectar se uma string está presente na stdout sem afetar a saída? [duplicado]

1

Eu tenho um programa chamado my_program que imprime mensagem de diagnóstico para stdout

Eu quero detectar se as mensagens de diagnóstico incluem a string "TEST FAILURE" e, se isso acontecer, executar algum comando após o término do programa.

A resposta mais próxima que encontrei é

if [ !my_program | grep "TEST FAILURE" ]
then
some_cmd
fi

No entanto, este método silencia todas as mensagens de diagnóstico. Eu ainda quero que as mensagens sejam mostradas no stdout. Alguns sugerem primeiro rodar o programa sem usar grep , então executar o programa pela segunda vez e canalizar para grep , porém meu programa leva 1 hora para rodar, eu quero evitar rodar um programa grande duas vezes.

Alguma opinião?

    
por Allen Kuo 18.08.2018 / 01:16

2 respostas

0

Você pode usar tee para enviar a saída do comando para grep e seu terminal ( /dev/tty ):

# Note grep's stdout is redirected to /dev/null
# because we only care about its exit code
if echo foo | tee /dev/tty | grep foo > /dev/null; then
  echo OK
fi

Da estrutura de diretórios e dispositivos do POSIX :

/dev/tty

In each process, a synonym for the controlling terminal associated with the process group of that process, if any. It is useful for programs or shell procedures that wish to be sure of writing messages to or reading data from the terminal no matter how output has been redirected. It can also be used for applications that demand the name of a file for output, when typed output is desired and it is tiresome to find out what terminal is currently in use.

Não ajudará se você quiser que a saída do comando seja redirecionada para a saída padrão do script, que pode não ser o terminal.

Você pode salvar a saída do comando para processamento adicional:

# Save output in a variable (or a regular file, a named pipe, etc.)
output="$(echo foo)"

# Dump output to script's stdout
cat <<< "${output}"

# Check if output matches some pattern
if grep foo <<< "${output}" > /dev/null; then
  echo OK
fi
    
por 18.08.2018 / 03:41
0

Usar um loop no bash também pode resolver seu problema:

#!/bin/bash

flagfile=/tmp/flagfile.$$.something

my_program | while read line ; do 
    if echo "$line" | grep "TEST FAILURE" 
    then
        touch $flagfile
    else
        echo "$line"
    fi
done

if [ -f $flagfile ] ; then
    rm -f $flagfile
    some_cmd
fi

Note que você não pode usar uma variável flag porque o loop while será executado em uma subshell.

    
por 18.08.2018 / 13:05