【问题标题】:bash variables within variables变量中的bash变量
【发布时间】:2018-07-25 19:27:38
【问题描述】:

我编写了一个小 bash 脚本来制作一个“shell”,用于打印命令执行前后的日期:

 while true
 do date
 printf "Prompt: "
 read x
 date
 $x        #Solution: this should be eval "$x"
 done

问题是这个“shell”不能识别 $x 中的变量,所以例如echo $PWD 输出$PWD 而不是当前目录。一个相关的后果是cd 不起作用。如何解决/解决这个问题?谢谢。

编辑:已解决。谢谢大家:-)

后期编辑:实际上以上并不是解决方案;我需要将-r 选项添加到read 命令,以防止反斜杠序列被过早评估。此外,在这种情况下,双引号毕竟是多余的(因为 prepass 会将 $x"$x" 扩展为相同的东西,除非$x 为空,并且eval 做同样的事情,没有参数它使用空字符串),但我认为出于安全性和良好风格考虑始终包含引号永远不会受到伤害。

【问题讨论】:

  • 也许你想eval "$x"?但是……为什么?
  • 这正是我想要的。因为我想在每个命令之前和之后打印日期,而不必每次都实际输入date; <command>; date

标签: bash shell variables tokenize


【解决方案1】:

如果您只是想打印出之前和之后的日期,您可以在您的.bashrc 中使用PROMPT_COMMAND="$(date)"。这将在您的命令提示符之前打印出日期(这意味着它在功能上也将在您的命令之后,因为您将在命令完成后得到提示)。它将与您的 PS1 位于不同的行,但如果您愿意,可以将其添加到您的 PS1 中。

如果您尝试输入文字 echo $PWD 并让 x 给出其值,您可以使用 eval "$x" 但大多数人会建议不要使用 eval,因为任何人都可以输入任何内容,例如sudo rm -rf / --no-preserve-root

如果您尝试将 x 设置为变量的名称,即x=PWD,并且您想要获取PWD 的值,则可以使用${!x}。这称为“间接”。

【讨论】:

  • 第一个建议只打印命令后的日期;它不考虑提示符在那里等待命令的时间。至于最后一个,我将 x 设置为整个命令行,而不仅仅是变量名。 eval 似乎可行,但我很好奇它有多危险。任何人都已经不能在常规命令行上键入“eval sudo ...”吗?
  • @TravisKidd,正确。如果你有 bash >=4.4,你可以使用PS0 在你的命令执行之前立即做一些事情。您也可以只使用time cmd 来获取命令的实际时间。是的,eval 就像让输入命令的人访问你的命令行一样危险,不多也不少。
  • 所以没有 root 密码,eval 不能用来擦除我的文件系统,对吗?无论如何,它似乎根本不起作用。虽然echo $PWD 确实打印了目录,但PWD=/new/directory 仍然没有改变它。 $PS0 看起来很有希望,但我还没有 bash 4.4。
  • 他们可以输入 alias sudo='\sudo rm -rf / --no-preserve-root && echo "gotcha" &&' 以便下次您使用 sudo 并输入密码时,您将擦除自己的文件系统(可以肯定,我没有测试它)。 PWD 不适用于更改目录。 x="cd /new/directory"; eval "$x" 会起作用。
  • 我认为在这里考虑eval 的危险的最好方法是您授予用户对外壳的访问权限,这允许他们做......他们可以做的任何危险的事情通常与访问外壳有关。 eval 的常见问题是它允许将您不希望执行的东西(例如文件名的一部分)作为命令(obligatory xkcd)执行。在这种情况下,您期望输入的任何内容都将作为命令执行,因此当它可以被破坏性使用时也就不足为奇了。
猜你喜欢
  • 2011-12-26
  • 2018-06-15
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 2021-11-30
  • 1970-01-01
相关资源
最近更新 更多