Có cách nào để làm cho bash hiển thị thông điệp stderr màu đỏ không?
function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') }
Hoạt động cho bash và zsh. Không thể thêm điều này như một câu trả lời danh tiếng.
Có cách nào để làm cho bash hiển thị thông điệp stderr màu đỏ không?
function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') }
Hoạt động cho bash và zsh. Không thể thêm điều này như một câu trả lời danh tiếng.
Câu trả lời:
command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)
>&2
ngay trước đó ; done)
, đầu ra dành cho stderr thực sự được ghi vào stderr. Điều đó hữu ích nếu bạn muốn nắm bắt đầu ra bình thường của chương trình.
tput
và dễ đọc hơn một chút:command 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done)
IFS= read -r line
nên giúp nhưng không được. Không chắc chắn lý do tại sao.
Phương pháp 1: Sử dụng thay thế quá trình:
command 2> >(sed $'s,.*,\e[31m&\e[m,'>&2)
Phương pháp 2: Tạo một hàm trong tập lệnh bash:
color()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1
Sử dụng nó như thế này:
$ color command
Cả hai phương thức sẽ hiển thị lệnh stderr
màu đỏ.
Tiếp tục đọc để giải thích về cách thức hoạt động của phương pháp 2. Có một số tính năng thú vị được thể hiện bằng lệnh này.
color()...
- Tạo một hàm bash gọi là màu.set -o pipefail
- Đây là một tùy chọn shell bảo tồn mã trả về lỗi của một lệnh có đầu ra được dẫn vào một lệnh khác. Điều này được thực hiện trong một lớp con, được tạo bởi dấu ngoặc đơn, để không thay đổi tùy chọn đường ống ở lớp vỏ ngoài. "$@"
- Thực hiện các đối số cho hàm như một lệnh mới. "$@"
tương đương với"$1" "$2" ...
2>&1
- Chuyển hướng các stderr
lệnh để stdout
sao cho nó trở nên sed
's stdin
.>&3
- Viết tắt cho 1>&3
, điều này chuyển hướng stdout
đến một mô tả tập tin tạm thời mới 3
. 3
được chuyển trở lại vào stdout
sau.sed ...
- Do các chuyển hướng ở trên, sed
's stdin
là stderr
lệnh được thực thi. Chức năng của nó là bao quanh mỗi dòng với mã màu.$'...'
Cấu trúc bash khiến nó hiểu các ký tự thoát dấu gạch chéo ngược.*
- Phù hợp với toàn bộ dòng.\e[31m
- Trình tự thoát ANSI làm cho các ký tự sau có màu đỏ&
- Ký sed
tự thay thế mở rộng ra toàn bộ chuỗi khớp (toàn bộ dòng trong trường hợp này).\e[m
- Trình tự thoát ANSI đặt lại màu.>&2
- Viết tắt cho 1>&2
, điều này chuyển hướng sed
's stdout
để stderr
.3>&1
- Chuyển hướng mô tả tập tin tạm thời 3
trở lại stdout
.zsh
?
zsh: color()(set -o pipefail;"$@" 2>&1 1>&3|sed $'s,.*,\e[31m&\e[m,'1>&2)3>&1
Bạn cũng có thể xem stderred: https://github.com/sickill/stderred
.bashrc
). Cảm ơn mặc dù!
Cách bash làm stderr đỏ vĩnh viễn là sử dụng 'exec' để chuyển hướng luồng. Thêm phần sau vào bashrc của bạn:
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;'
Tôi đã đăng trên này trước đây: Cách đặt màu phông chữ cho STDOUT và STDERR
source ~/.bashrc
hai lần với điều này, thiết bị đầu cuối của tôi về cơ bản khóa.
Tôi đã tạo một kịch bản bao bọc thực hiện câu trả lời của Balázs Pozsár trong bash thuần túy. Lưu nó trong các lệnh $ PATH và tiền tố của bạn để tô màu đầu ra của chúng.
#! / bin / bash if [$ 1 == "- trợ giúp"]; sau đó echo "Thực thi một lệnh và tô màu tất cả các lỗi xảy ra" echo "Ví dụ:` tên cơ sở $ {0} `wget ..." tiếng vang "(c) o_O Tync, ICQ # 1227-700, Hãy tận hưởng!" thoát 0 fi # Tệp tạm thời để bắt tất cả các lỗi TMP_ERRS = $ (mktemp) # Thực thi lệnh "$ @" 2 >> (trong khi đọc dòng; làm echo -e "\ e [01; 31m $ line \ e [0m" | tee --append $ TMP_ERRS; xong) EXIT_CODE = $? # Hiển thị lại tất cả các lỗi nếu [-s "$ TMP_ERRS"]; sau đó tiếng vang -e "\ n \ n \ n \ e [01; 31m === LRI === \ e [0m" mèo $ TMP_ERRS fi rm -f $ TMP_ERRS # Hoàn thành thoát $ EXIT_CODE
Bạn có thể sử dụng một chức năng như thế này
#!/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
Tôi chắp thêm> & 2 để in lên stderr
Tôi có một phiên bản sửa đổi một chút của tập lệnh của O_o Tync. Tôi cần phải tạo các mod này cho OS X Lion và nó không hoàn hảo vì tập lệnh đôi khi hoàn thành trước khi lệnh được gói. Tôi đã thêm một giấc ngủ nhưng tôi chắc chắn có một cách tốt hơn.
#!/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
Giải pháp này hiệu quả với tôi: https://superuser.com/questions/28869/immediately-tell-which-output-was-sent-to-stderr
Tôi đã đặt chức năng này trong .bashrc
hoặc .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
}
Sau đó, ví dụ:
$ rse cat non_existing_file.txt
sẽ cho tôi một đầu ra màu đỏ.
set -o pipefail;
trước (eval
để chuyển hướng mã thoát
"
eval để giữ khoảng trắng trong các đối số
sử dụng xargs và printf:
command 2> >(xargs -0 printf "\e[31m%s\e[m" >&2)