如何根据 bash 中的变量有条件地将输出重定向到文件

如何根据 bash 中的变量有条件地将输出重定向到文件

我正在尝试使用 eval 命令来评估评论 - 我不确定这是否是正确的方法。例子:

i=??(我在这里想要的是一个#,来评论后面的内容,或者空白)

somecommand arg1 arg2 $(eval $i) >> file

因此,根据$i值,它必须是:

somecommand arg1 arg2 # >> file从“不打印到文件”开始

或者

somecommand arg1 arg2 >> file从“打印到文件”开始

为了更清楚起见,示例脚本:

i=true

somecommand arg1 arg2 >> file1
[some code]
somecommand arg1 arg2 >> file2
[some code]
somecommand arg1 arg2 >> file3
[some code]
And so on...

$i我希望它仅在为真时才将输出打印到文件中;或者,正如我最初尝试的那样,对eval$i 进行注释并注释“输出到文件”的代码段。

我问是因为我认为有一种比这样做更优雅的方法:

if $i
then
   somecommand arg1 arg2 >> file3
else
   somecommand arg1 arg2
fi

答案1

你总是可以这样做:

unset -v log
# or
log=true
([ -z "$log" ] || exec >> file1; somecommand arg1 arg2)
([ -z "$log" ] || exec >> file2; somecommand arg1 arg2)

或者:

if [ -n "$log" ]; then
  exec 3>> file1 4>> file2
else
  exec 3>&1 4>&1
fi
somecommand arg1 arg2 >&3
somecommand arg1 arg2 >&4

或者:

log() {
  local output="$1"; shift
  if [ -n "$output" ]; then
    "$@" >> "$output"
  else
    "$@" 
  fi
}

log "${log+file1}" somecommand arg1 arg2
log "${log+file2}" somecommand arg1 arg2

或者(确保传递到的数据eval不是动态的,以避免代码注入漏洞,因此使用下面的单引号,其中不会发生扩展):

eval ${log+'>> file1'} 'somecommand arg1 arg2'
eval ${log+'>> file2'} 'somecommand arg1 arg2'

zsh

if (($+log)); then
  alias -g 'log?=>>'
else
  alias -g 'log?=#'
fi

somecommand arg1 arg2 log? file1
somecommand arg1 arg2 log? file2

或者甚至(如果您不打算>>用于除这种条件日志记录之外的任何其他用途):

(($+log)) || alias -g '>>=#'

somecommand arg1 arg2 >> file1
somecommand arg1 arg2 >> file2

bash没有alias -g,不允许您使用诸如 之类的别名,但是如果您将重定向移至开头,则>>可以使用简单的es :alias

shopt -s expand_aliases
skip_one() { shift; "$@"; }
if [[ -v log ]]; then
  alias 'log?=>>'
else
  alias 'log?=skip_one'
fi

log? file1 somecommand arg1 arg2
log? file2 somecommand arg1 arg2

相关内容