Existe uma maneira de fazer o bash exibir mensagens stderr na cor vermelha?
function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') }
funciona para o bash e o zsh. Não é possível adicionar isso como resposta b / c reputação.
Existe uma maneira de fazer o bash exibir mensagens stderr na cor vermelha?
function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') }
funciona para o bash e o zsh. Não é possível adicionar isso como resposta b / c reputação.
Respostas:
command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)
>&2
um pouco antes ; done)
, a saída destinada ao stderr é realmente gravada no stderr. Isso é útil se você deseja capturar a saída normal do programa.
tput
, e é ligeiramente mais legível na minha opinião:command 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done)
IFS= read -r line
deve ajudar, mas não ajuda. Não sei por que.
Método 1: Usar substituição de processo:
command 2> >(sed $'s,.*,\e[31m&\e[m,'>&2)
Método 2: Crie uma função em um script bash:
color()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1
Use-o assim:
$ color command
Ambos os métodos mostrarão os comandos stderr
em vermelho.
Continue lendo para obter uma explicação de como o método 2 funciona. Existem alguns recursos interessantes demonstrados por este comando.
color()...
- Cria uma função bash chamada cor.set -o pipefail
- Esta é uma opção de shell que preserva o código de retorno de erro de um comando cuja saída é canalizada para outro comando. Isso é feito em um subshell, criado pelos parênteses, para não alterar a opção de pipefail no shell externo. "$@"
- Executa os argumentos para a função como um novo comando. "$@"
é equivalente a"$1" "$2" ...
2>&1
- Redireciona o stderr
do comando para stdout
modo que se torna sed
's stdin
.>&3
- Abreviação de 1>&3
, isso redireciona stdout
para um novo descritor de arquivo temporário 3
. 3
é roteado de volta para stdout
mais tarde.sed ...
- Por causa dos redirecionamentos acima, sed
's stdin
é o stderr
comando executado. Sua função é cercar cada linha com códigos de cores.$'...'
Uma construção bash que faz com que ele entenda caracteres com escape de barra invertida.*
- Corresponde a linha inteira.\e[31m
- A sequência de escape ANSI que faz com que os seguintes caracteres fiquem vermelhos&
- O sed
caractere de substituição que se expande para toda a cadeia correspondente (a linha inteira nesse caso).\e[m
- A sequência de escape ANSI que redefine a cor.>&2
- Abreviação para 1>&2
, este redireciona sed
's stdout
para stderr
.3>&1
- Redireciona 3
novamente o descritor de arquivo temporário stdout
.zsh
?
zsh: color()(set -o pipefail;"$@" 2>&1 1>&3|sed $'s,.*,\e[31m&\e[m,'1>&2)3>&1
Você também pode conferir stderred: https://github.com/sickill/stderred
.bashrc
). Obrigado embora!
A maneira básica de tornar o stderr permanentemente vermelho é usar 'exec' para redirecionar fluxos. Adicione o seguinte ao seu bashrc:
exec 9>&2
exec 8> >(
while IFS='' read -r line || [ -n "$line" ]; do
echo -e "\033[31m${line}\033[0m"
done
)
function undirect(){ exec 2>&9; }
function redirect(){ exec 2>&8; }
trap "redirect;" DEBUG
PROMPT_COMMAND='undirect;'
Eu postei isso anteriormente: Como definir a cor da fonte para STDOUT e STDERR
source ~/.bashrc
duas vezes, meu terminal basicamente trava.
Eu criei um script de wrapper que implementa a resposta de Balázs Pozsár em pura festa. Salve-o em seus comandos $ PATH e prefix para colorir sua saída.
#! / bin / bash if [$ 1 == "--help"]; então echo "Executa um comando e colore todos os erros ocorridos" echo "Exemplo:` nome da base $ {0} `wget ..." eco "(c) o_O Tync, ICQ # 1227-700, divirta-se!" saída 0 fi # Arquivo temporário para capturar todos os erros TMP_ERRS = $ (mktemp) # Executar comando "$ @" 2>> (enquanto lê a linha; faça eco-e "\ e [01; 31m $ line \ e [0m" | tee - adicione $ TMP_ERRS; pronto) EXIT_CODE = $? # Exibe todos os erros novamente if [-s "$ TMP_ERRS"]; então eco -e "\ n \ n \ n \ e [01; 31m === ERROS === \ e [0m" cat $ TMP_ERRS fi rm -f $ TMP_ERRS # Terminar sair $ EXIT_CODE
Você pode usar uma função como esta
#!/bin/sh
color() {
printf '\033[%sm%s\033[m\n' "$@"
# usage color "31;5" "string"
# 0 default
# 5 blink, 1 strong, 4 underlined
# fg: 31 red, 32 green, 33 yellow, 34 blue, 35 purple, 36 cyan, 37 white
# bg: 40 black, 41 red, 44 blue, 45 purple
}
string="Hello world!"
color '31;1' "$string" >&2
Anexo> & 2 para imprimir em stderr
Eu tenho uma versão ligeiramente modificada do script do O_o Tync. Eu precisava fazer esses mods para o OS X Lion e não é perfeito porque o script às vezes é concluído antes do comando finalizado. Adicionei um sono, mas tenho certeza de que há uma maneira melhor.
#!/bin/bash
if [ $1 == "--help" ] ; then
echo "Executes a command and colorizes all errors occured"
echo "Example: `basename ${0}` wget ..."
echo "(c) o_O Tync, ICQ# 1227-700, Enjoy!"
exit 0
fi
# Temp file to catch all errors
TMP_ERRS=`mktemp /tmp/temperr.XXXXXX` || exit 1
# Execute command
"$@" 2> >(while read line; do echo -e "$(tput setaf 1)$line\n" | tee -a $TMP_ERRS; done)
EXIT_CODE=$?
sleep 1
# Display all errors again
if [ -s "$TMP_ERRS" ] ; then
echo -e "\n\n\n$(tput setaf 1) === ERRORS === "
cat $TMP_ERRS
else
echo "No errors collected in $TMP_ERRS"
fi
rm -f $TMP_ERRS
# Finish
exit $EXIT_CODE
Esta solução funcionou para mim: https://superuser.com/questions/28869/immedately-tell-which-output-was-sent-to-stderr
Eu coloquei essa função no meu .bashrc
ou .zshrc
:
# Red STDERR
# rse <command string>
function rse()
{
# We need to wrap each phrase of the command in quotes to preserve arguments that contain whitespace
# Execute the command, swap STDOUT and STDERR, colour STDOUT, swap back
((eval $(for phrase in "$@"; do echo -n "'$phrase' "; done)) 3>&1 1>&2 2>&3 | sed -e "s/^\(.*\)$/$(echo -en \\033)[31;1m\1$(echo -en \\033)[0m/") 3>&1 1>&2 2>&3
}
Então, por exemplo:
$ rse cat non_existing_file.txt
vai me dar uma saída vermelha.
set -o pipefail;
antes (eval
para o código de saída de redirecionamento
"
to eval para preservar espaços nos argumentos
usando xargs e printf:
command 2> >(xargs -0 printf "\e[31m%s\e[m" >&2)
uma versão usando fifos
mkfifo errs
stdbuf -o0 -e0 -i0 grep . foo | while read line; do echo -e "\e[01;31m$line \e[0m" >&2; done &
stdbuf -o0 -e0 -i0 sh $script 2>errs