在 bash 中用其内容替换“源文件”并扩展变量

Fré*_*iza 5 bash set expansion subshell

在 script.sh 中,

source a.sh
source b.sh

CMD1
CMD2
CMD3
Run Code Online (Sandbox Code Playgroud)

如何source *.sh用它们的内容替换(不执行命令)?我想看看 bash 解释器在获取文件并扩展所有变量后执行什么。

我知道我可以使用set -n -v或运行bash -n -v script.sh 2>output.sh,但这不会替换源命令(如果 a.sh 或 b.sh 包含变量,则更少)。

我想过使用子shell,但这仍然没有扩展源代码行。我在源代码行之前和之后尝试了set +n +v和的组合set -n -v,但这仍然不起作用。

我将使用 ssh 将该输出发送到远程机器。我可以使用<<output.sh管道将内容传输到 ssh 命令中,但我无法以 root 身份登录到远程计算机,但我是 sudoer。因此,我想我可以创建脚本并将其作为 base64 编码的字符串发送(使用那个聪明的技巧base64 script | ssh remotehost 'base64 -d | sudo bash'

有解决办法吗?或者你有更好的主意吗?

dim*_*mid 6

你可以这样做:

内联.sh:

#!/usr/bin/env bash
while read line; do
    if [[ "$line" =~ (\.|source)\s+.+ ]]; then
        file="$(echo $line | cut -d' ' -f2)"
        echo "$(cat $file)"
    else
      echo "$line"
    fi
done < "$1"
Run Code Online (Sandbox Code Playgroud)

请注意,这假定sourced 文件存在,并且不处理错误。您还应该处理可能的 hashbangs。如果sourced文件包含自己source,则需要递归地应用脚本,例如(未测试):

while egrep -q '^(source|\.)' main.sh; do
    bash inline.sh main.sh > main.sh
done
Run Code Online (Sandbox Code Playgroud)

让我们测试一下

主文件:

source a.sh
. b.sh

echo cc
echo "$var_a $var_b"
Run Code Online (Sandbox Code Playgroud)

灰:

echo aa
var_a="stack" 
Run Code Online (Sandbox Code Playgroud)

b.sh:

echo bb
var_b="overflow"
Run Code Online (Sandbox Code Playgroud)

结果:

bash inline.sh main.sh

echo aa
var_a="stack"
echo bb
var_b="overflow"

echo cc
echo "$var_a $var_b"

bash inline.sh main.sh | bash

aa
bb
cc
stack overflow
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果你只是想看看 bash 执行了什么,你可以运行

bash -x [script]
Run Code Online (Sandbox Code Playgroud)

或远程

ssh user@host -t "bash -x [script]"
Run Code Online (Sandbox Code Playgroud)

  • 对于任何为此苦苦挣扎的人,我开发了一个与 ShellCheck 兼容且完全可定制的 POSIX 脚本:https://github.com/carlocorradini/inline (2认同)