【问题标题】:evaluate a command in a while loop in bash [duplicate]在bash的while循环中评估命令[重复]
【发布时间】:2021-03-22 23:34:41
【问题描述】:

我正在尝试编写一个代码,该代码在根据用户输入确定的文件列表上运行脚本。由于某种原因,以下代码不起作用?有什么方法可以评估 query_cmd 并遍历它输出的文件。

if [[ $# -gt 0 && "$1" == "--diff" ]]; then
  query_cmd="git diff --name-only '*.cc' '*.h'"
else
  query_cmd='find . \( -name "*.cc" -o -name "*.h" \)'
fi

while IFS='' read -r line; do
  absolute_filepath=$(realpath "$line")
  if [[ $absolute_filepath =~ $ignore_list ]]; then
     continue
  fi
  cpp_filepaths+=("$absolute_filepath")
done < <($query_cmd)

【问题讨论】:

  • $(..) 已经对其进行了评估。试试echo "$query_cmd"
  • @thatotherguy 抱歉,我的问题有误。
  • 在变量中存储复杂的命令不起作用。要么使用数组,要么将整个 if 块放在 &lt; &lt;(...) 表达式中。见"Why does shell ignore quoting characters in arguments passed to it through variables?"BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!
  • @MrR,不,由于我描述的原因,它在 OP 的情况下不起作用。在 $query_cmd 字符串中包含文字文本 '*.cc' 意味着命令在解析时需要使用引号。当它们被解析时,它们被视为文字字符。
  • git expects 形式为["git", "diff", "--name-only", "*.cc", "*.h"](JSON 转义)的命令行,这是shell 在解析和执行git diff --name-only '*.cc' '*.h' 作为代码时将执行的操作。运行 $query_cmd 将改为运行 ["git", "diff", "--name-only", "'*.cc'", "'*.h'"],添加 literal 单引号,在正常解析的命令中将被 shell 删除。

标签: bash


【解决方案1】:

一般来说,如果你有想要稍后运行的代码,你会把它放在一个函数中,而不是放在一个字符串中:

if [[ $# -gt 0 && "$1" == "--diff" ]]; then
  query_cmd() {
    git diff --name-only '*.cc' '*.h'
  }
else
  query_cmd() {
    find . \( -name "*.cc" -o -name "*.h" \)
  }
fi

while IFS='' read -r line; do
  ...
done < <(query_cmd)

但如果您喜欢额外的转义挑战,您可以使用字符串并使用eval 评估它们:

if [[ $# -gt 0 && "$1" == "--diff" ]]; then
  query_cmd="git diff --name-only '*.cc' '*.h'"
else
  query_cmd='find . \( -name "*.cc" -o -name "*.h" \)'
fi

while IFS='' read -r line; do
  ...
done < <(eval "$query_cmd")

【讨论】:

  • 在演示eval 之前,我会考虑展示使用数组来存储命令行。 (如果愿意,我很乐意自己为此进行编辑)。
  • 我不知道...我为 OP 应该提出的问题以及他们确实提出的字面问题提供了(可以说)最佳解决方案。在这种特定情况下,数组似乎是两全其美
  • 并且也可以用函数中的if来做函数方法,而不是有2个变种..
  • @thatotherguy,回复:arrays-as-worst-of-both-worlds,怎么会这样? query_cmd=( git diff --name-only '*.cc' '*.h' ) 然后 &lt; &lt;("${query_cmd[@]}")... 什么不干净?您没有额外的转义挑战,您可以修改命令,在其参数中使用变量,而不会引入安全错误。
猜你喜欢
  • 1970-01-01
  • 2016-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-05
  • 1970-01-01
  • 2020-10-29
  • 2019-12-19
相关资源
最近更新 更多