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

Ray*_*ndo 4 bash eval

我正在尝试使用 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...
Run Code Online (Sandbox Code Playgroud)

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

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

if $i
then
   somecommand arg1 arg2 >> file3
else
   somecommand arg1 arg2
fi
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 7

你总是可以这样做:

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

或者:

if [ -n "$log" ]; then
  exec 3>> file1 4>> file2
else
  exec 3>&1 4>&1
fi
somecommand arg1 arg2 >&3
somecommand arg1 arg2 >&4
Run Code Online (Sandbox Code Playgroud)

或者:

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

log "${log+file1}" somecommand arg1 arg2
log "${log+file2}" somecommand arg1 arg2
Run Code Online (Sandbox Code Playgroud)

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

eval ${log+'>> file1'} 'somecommand arg1 arg2'
eval ${log+'>> file2'} 'somecommand arg1 arg2'
Run Code Online (Sandbox Code Playgroud)

zsh

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

somecommand arg1 arg2 log? file1
somecommand arg1 arg2 log? file2
Run Code Online (Sandbox Code Playgroud)

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

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

somecommand arg1 arg2 >> file1
somecommand arg1 arg2 >> file2
Run Code Online (Sandbox Code Playgroud)

bash没有alias -g, 不允许您为诸如 之类的东西添加别名>>,但是alias如果您将重定向移动到开头,则可以使用 simple es:

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
Run Code Online (Sandbox Code Playgroud)