运行从 stdin 传输的多行 bash 脚本

运行从 stdin 传输的多行 bash 脚本

我正在寻找一种简单的方法将多行脚本内联到文档中,以使每个步骤的作用变得透明。

这有效

echo "echo 1234" | bash

这也是

echo 'for N in 1 2 3; do echo $N; done' | bash

不过,我想使用这样的东西(但它不起作用):

echo <<EOF | bash
for N in 1 2 3; do
echo "N is ${N}"
done
EOF

更新,迄今为止最接近的有效解决方案是:

cat <<EOF|bash
for N in 1 2 3 4; do
    echo "N is now \$N"
done
EOF

但理想情况下,我不希望逃离\$N

正确的解决方案不会:

  • 使用未安装的工具默认 Debian 配置
  • 涉及临时文件
  • 下载脚本(curl -o - htpp://blah.com/script | bash等)

理想情况下,它是读者可以复制粘贴、按下回车键并无需进一步操作即可执行的内容。

答案1

如果引用或转义此处的文档分隔符(即<<'EOF'或 而<<\EOF不仅仅是<<EOF),则 shell 不会对内容进行扩展(变量等)。

cat <<'EOF' | bash
for N in 1 2 3; do
echo "N is ${N}"
done
EOF

顺便说一句,这个cat命令在这里并没有真正做任何有用的事情(它只是所谓的“无用的 cat” 或 UUoC)。您可以将其消除并直接将输入发送至bash

bash <<'EOF'
for N in 1 2 3; do
echo "N is ${N}"
done
EOF

如果代码片段需要读取输入,那就有点棘手了,因为脚本的输入是...脚本片段本身。在大多数类 Unix 操作系统上,您可以通过将脚本传递到不同的文件描述符并告诉bash“执行”该文件描述符来避免这种情况:

bash /dev/fd/3 3<<'EOF'
read -p "Enter something here: " input
echo "You entered: ${input}"
EOF

但请注意,这些代码片段之一中设置的任何变量(如$input这里)都仅在该 shell 进程中设置,并且在退出时将会丢失。

答案2

我认为你能做的最好的事情是这样的:

bash -c '
    echo "Simple scriptlike thingy"
    for I in 1 2 3 45; do
      echo "I is now ${I}"
    done
'

请注意,这实际上是将 while 脚本作为参数传递给-cswitch,而该参数本身将被解析bash。这就是为什么你不能使用"这样的符号:

bash -c "
    THING=text
    echo this will not work: $THING
"

因为在参数中,$THING在作为参数传递之前被替换,并且由于THING未设置,它将被替换为空字符串。用撇号括起来的字符串不会被解析,因此它可用于包含要在“第二个 bash 进程”解析脚本时设置的变量。

对于更复杂的脚本,我认为最好的方法是让读者保存脚本并运行它,但对于简单的构造,上述方法应该有效。

相关内容