É possível modelar/substituir STDOUT?

É possível modelar/substituir STDOUT?

Estou depurando uma pilha de chamadas e simplesmente gerando echoinstruções de vários arquivos. Os registros planos estão se tornando um pouco difíceis de seguir, então estou curioso para saber qual pode ser a melhor maneira de aninhar a saída.

Achei que definir uma variável de ambiente para o número de guias ou como uma string de espaço/tabulação de prefixo poderia ser a opção mais fácil se eu pudesse sobrecarregar o fluxo STDOUT. Basicamente, seria bom se eu pudesse fazer algo como STDOUT="$TABS$STDOUT"continuar empilhando caracteres de tabulação no início do fluxo de saída.

Mas eu não tinha certeza se era possível substituir o fluxo. Por exemplo, se eu quisesse prefixar cada linha com um hífen + espaço, isso seria possível?

De tal modo que:

echo foo
echo bar
echo foobar

Produz:

- foo
- bar
- foobar

  1. A modelagem STDOUT é possível?
  2. Qual é o método sugerido para aninhar a saída, sem precisar modificar todas as instruções echo/ printfnos vários scripts que podem ser chamados?

Responder1

Provavelmente a coisa mais fácil de fazer, se você não se importa em mesclar stdout e stderr, é executar com o -xsinalizador que faz o bash imprimir cada comando conforme ele é executado com um prefixo como +++o local onde o número de caracteres vem do nível de aninhamento. Você pode então pós-processar a saída, lembrando o prefixo, mas suprimindo a linha, e aplicando-a a qualquer linha não prefixada seguinte, que será seu echo ou printf.

Por exemplo, pegue um pequeno script fatorial myprog:

#!/bin/bash
f(){
        local i=$1
        if [[ "$i" > 1 ]]
        then        echo $((i*$(f $((i-1)))))
        else        echo $i
        fi
        echo "my debug info $i" >&2
}
echo "factorial ${1?} is $(f $1)"

Executando com

 bash -x myprog 4  |&
 awk '/^+/{ indent=$1; next }
          { print indent " " $0 }'

da-te

+++++ my debug info 1
++++ my debug info 2
+++ my debug info 3
++ my debug info 4
+ factorial 4 is 24

Claro, você pode obter uma boa saída de depuração com números de linha, nomes de arquivos e funções apenas configurando PS4com -x. Por exemplo

PS4='+ ${BASH_SOURCE}:${LINENO}: ${FUNCNAME[0]} - [${SHLVL},${BASH_SUBSHELL}, $?]     ' 

da-te:

++ myprog:10: main - [2,1, 0]     f 4
++ myprog:3: f - [2,1, 0]     local i=4
++ myprog:4: f - [2,1, 0]     [[ 4 > 1 ]]
+++ myprog:5: f - [2,2, 0]     f 3
+++ myprog:3: f - [2,2, 0]     local i=3
+++ myprog:4: f - [2,2, 0]     [[ 3 > 1 ]]
++++ myprog:5: f - [2,3, 0]     f 2
++++ myprog:3: f - [2,3, 0]     local i=2
++++ myprog:4: f - [2,3, 0]     [[ 2 > 1 ]]
...

informação relacionada