脚本中详细模式的优雅方式?

tam*_*gal 27 bash logging verbosity

当我编写bash脚本时,我通常会以这种方式获得详细模式(简化):

_V=0

while getopts "v" OPTION
do
  case $OPTION in
    v) _V=1
       ;;
  esac
done
Run Code Online (Sandbox Code Playgroud)

然后每次我想要一个"详细输出"我输入:

[ $_V -eq 1 ] && echo "verbose mode on" || echo "verbose mode off"
Run Code Online (Sandbox Code Playgroud)

或者例如:

[ $_V -eq 1 ] && command -v || command
Run Code Online (Sandbox Code Playgroud)

有没有办法让它更优雅?我正在考虑定义一个名为"verbose"的函数并将其键入而不是[ $_V -eq 1 ],但这只是一个微小的改进.

我敢肯定,有更常见的方式来做到这一点......

ДМИ*_*КОВ 35

当你发现,你可以定义一些log类似的功能log,log_debug,log_error,等.

function log () {
    if [[ $_V -eq 1 ]]; then
        echo "$@"
    fi
}
Run Code Online (Sandbox Code Playgroud)

它可以帮助提高主代码的可读性,并将show \nonshow逻辑隐藏到日志记录功能中.

log "some text"

如果_V(全局变量)相等,1将打印"some text",在其他情况下则不会.


fen*_*tas 17

阅读完所有其他帖子后,我想出了这个

# set verbose level to info
__VERBOSE=6

declare -A LOG_LEVELS
# https://en.wikipedia.org/wiki/Syslog#Severity_level
LOG_LEVELS=([0]="emerg" [1]="alert" [2]="crit" [3]="err" [4]="warning" [5]="notice" [6]="info" [7]="debug")
function .log () {
  local LEVEL=${1}
  shift
  if [ ${__VERBOSE} -ge ${LEVEL} ]; then
    echo "[${LOG_LEVELS[$LEVEL]}]" "$@"
  fi
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样简单地使用它

# verbose error
.log 3 "Something is wrong here"
Run Code Online (Sandbox Code Playgroud)

哪个会输出

[error] Something is wrong here
Run Code Online (Sandbox Code Playgroud)


小智 5

#!/bin/bash
# A flexible verbosity redirection function
# John C. Petrucci (http://johncpetrucci.com)
# 2013-10-19
# Allows your script to accept varying levels of verbosity flags and give appropriate feedback via file descriptors.
# Example usage: ./this [-v[v[v]]]

verbosity=2 #Start counting at 2 so that any increase to this will result in a minimum of file descriptor 3.  You should leave this alone.
maxverbosity=5 #The highest verbosity we use / allow to be displayed.  Feel free to adjust.

while getopts ":v" opt; do
    case $opt in
        v) (( verbosity=verbosity+1 ))
        ;;
    esac
done
printf "%s %d\n" "Verbosity level set to:" "$verbosity"

for v in $(seq 3 $verbosity) #Start counting from 3 since 1 and 2 are standards (stdout/stderr).
do
    (( "$v" <= "$maxverbosity" )) && echo This would display $v 
    (( "$v" <= "$maxverbosity" )) && eval exec "$v>&2"  #Don't change anything higher than the maximum verbosity allowed.
done

for v in $(seq $(( verbosity+1 )) $maxverbosity ) #From the verbosity level one higher than requested, through the maximum;
do
    (( "$v" > "2" )) && echo This would not display $v 
    (( "$v" > "2" )) && eval exec "$v>/dev/null" #Redirect these to bitbucket, provided that they don't match stdout and stderr.
done

# Some confirmations:
printf "%s\n" "This message is seen at verbosity level 3 and above." >&3
printf "%s\n" "This message is seen at verbosity level 4 and above." >&4
printf "%s\n" "This message is seen at verbosity level 5 and above." >&5
Run Code Online (Sandbox Code Playgroud)