【问题标题】:Evaluation of curly braces in LinuxLinux中花括号的评估
【发布时间】:2023-04-02 17:05:01
【问题描述】:

我注意到我们可以使用花括号来使某些命令更短,因为它被评估为参数列表。

输入:

echo a{,b,c}

输出:

a ab ac

当从文件中传递参数时,如何强制执行相同的行为?

输入:

cat file.txt | xargs echo

输出:

a{,b,c}

预期输出 - 与前面的示例相同。

【问题讨论】:

  • 如果不启用可以让文件中的内容运行任意脚本内容(即$(rm -rf ~))的解析阶段,您将无法执行此操作。最好不要这样做。

标签: linux bash xargs


【解决方案1】:

{} 扩展是 bash / zsh 功能,因此您需要通过任何这些 shell 显式运行它,在您的情况下是(使用 -I<STRING> 让 xargs 替换它运行前的字符串):

cat file.txt |xargs -I@ bash -c 'echo @' 

【讨论】:

    【解决方案2】:
    1. xargs 调用 $PATH 中的 echo,而不是 shell 的内置 echo。
    2. 检查list of bash expansions:大括号扩展首先发生,因此它不会有机会在该管道中扩展。

    你必须做类似的事情

    while read -r line; do eval echo "$line"; done < file.txt
    

    如果有人在该文件中放入恶意内容,这会使您面临各种讨厌的攻击。

    【讨论】:

      【解决方案3】:

      除了问你为什么要这样做...我提供以下内容:

      将字符串添加到文件中:

      echo 'a{,b,c}' > /tmp/foo
      

      将字符串放入变量中:

      export thing=`cat /tmp/foo`
      

      eval 字符串:

      eval $thing
      

      如果你在一个文件中有一堆这些,那么通过循环运行文件并评估循环值:

      echo 'a{,b,c}' >> /tmp/foo
      echo 'a{,b,c}' >> /tmp/foo
      echo 'a{,b,c}' >> /tmp/foo
      
      for i in `cat /tmp/foo`; do eval echo $i; done
      

      【讨论】:

      • export thing=$(cat /tmp/foo)中,export的退出状态会覆盖cat的退出状态,所以你不知道命令是否失败。最好将 thing=$(&lt;/tmp/foo); export thing 作为两个单独的命令。
      • 顺便说一句,最好把你的整个块放在像{ echo one; echo two; echo three; } &gt;/tmp/foo这样的重定向中,这样你就只打开一次输出文件——当你echo one &gt;/tmp/foo; echo two &gt;&gt;/tmp/foo; echo three &gt;&gt;/tmp/foo时,你正在打开和关闭输出文件三个不同的时间。
      • eval "$thing"eval $thing 更好;当您执行后者时,您将字符串拆分和全局扩展您的变量内容之前您将该进程创建的字符串列表发送到eval(以便将其重新组合成单​​个字符串发送到 shell 的解析器)。
      • 举个具体的例子,试试thing=' echo " * " ',然后比较eval $thingeval "$thing";你会看到他们有两个不同的结果。 (但是,如果您不相信当前目录中没有恶意命名的文件,请不要执行前者!如果有人在您所在的目录中运行了touch $'$(rm -rf ~)\'$(rm -rf ~)\'',那么之前的eval 很快通往糟糕的一天)。
      猜你喜欢
      • 1970-01-01
      • 2016-10-21
      • 2016-05-30
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-18
      • 1970-01-01
      相关资源
      最近更新 更多