【问题标题】:What is the difference between these two things?这两件事有什么区别?
【发布时间】:2019-02-03 00:07:50
【问题描述】:

我只是想知道两者有什么区别:

echo {$number1..$number2}

与

eval echo {$number1..$number2}

当然,假设 $number1 和 $number2 中有一个值。 使用第一个选项是行不通的,但使用第二个选项它可以工作。我不是那种只想让某事起作用的典型人,我想了解为什么会这样,为什么会这样?

【问题讨论】:

  • 一个 eval 可以执行任何命令。
  • 是的,但是,在第一种形式中,我也在执行命令。那么真正的区别是什么?过程?
  • This answer 在相关问题上解释了为什么大括号扩展不能与参数扩展一起使用
  • bash 手册页不是最容易阅读的,但 EXPANSION 部分可能会有所帮助。

标签: linux bash eval brace-expansion


【解决方案1】:

为什么第一个表达式没有按预期工作

  1. 在变量扩展之前执行大括号扩展。 $number1..$number2 不是有效的序列表达式,因此整个表达式保持不变。
  2. 之后,变量展开,产生表达式{1..3}(假设number1=1 和number2=3)。

为什么第二个表达式会这样做

您的第二个示例的工作原理相同,除了变量扩展 ({1..3}) 的结果通过 eval 再次传递给 Bash,给大括号扩展第二次机会:1..3 是一个正确格式的序列表达式,因此大括号扩展产生预期的结果:

1 2 3

避免使用eval

通常应避免使用eval,因为它很容易引入安全问题:如果number1 或number2 接收输入但未正确清理,则可能会将恶意代码注入您的程序。有关在各种用例中替换 eval 的方法,请参阅 this related question。

在您的具体示例中,可以通过结合算术评估的 for 循环创建序列:

for ((i=number1 ; i<=number2; i+=1)); do echo -n "$i" ; done | xargs
1 2 3

一种流行的非 Bash 解决方案是使用 seq(正如 Walter A 在 his answer 中指出的那样),就像在 seq "$number1" "$number2" | xargs 中一样。

注意:xargs 在这些示例中将多行输出连接到单行。

更多信息

answer to a related question 提供了有关该主题的更多信息。

此外,bash(1) manual page 中的 EXPANSION section 提供了有关不同扩展机制的顺序和工作方式的大量信息。

【讨论】:

    【解决方案2】:

    变量的替换为时已晚。
    您可以通过

    避免eval
    seq -s " " "$number1" "$number2"
    

    【讨论】:

      猜你喜欢
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      • 2022-06-10
      • 2011-04-06
      • 2019-05-15
      • 2016-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多