2016-05-30 43 views
2

在script.sh,更换“源文件”,其内容,扩大变量,在bash

source a.sh 
source b.sh 

CMD1 
CMD2 
CMD3 

我怎能取代source *.sh与他们的内容(不执行命令)? 我想知道在找到文件并扩展所有变量之后,bash解释器执行的是什么。

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

我想使用一个子shell,但仍然不扩展源代码行。在源代码行之前和之后,我尝试了set +n +vset -n -v的组合,但仍然无效。

我打算使用ssh将输出发送到远程机器。 我可以使用<<output.sh将内容传送到ssh命令中,但我无法以超级用户身份登录到远程计算机,但我是一个sudoer。 因此,我想我可以创建脚本,并把它作为(使用that clever trickbase64 script | ssh remotehost 'base64 -d | sudo bash'

是否有解决方案base64编码字符串? 或者你有更好的主意吗?

回答

2

你可以做这样的事情:

inline.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" 

注意这个假设存在source d文件,并且不处理错误。你也应该处理可能的hashbangs。如果sourced文件本身包含source,则需要递归应用脚本,例如,像(未测试):

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

测试一下

main.sh:

source a.sh 
. b.sh 

echo cc 
echo "$var_a $var_b" 

a.sh:

echo aa 
var_a="stack" 

b.sh:

echo bb 
var_b="overflow" 

结果:

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 

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

bash -x [script] 

或远程

ssh [email protected] -t "bash -x [script]" 
+0

您是否尝试过解决方案,当一个。 sh定义了一个变量,main.sh在'echo cc'之后调用它? 我不认为这个变量会被扩大。 是的,我已经知道-x。 该脚本是为了在远程机器上运行,而不是我的,但我想以编程方式编写它(即使用变量和某种包含) –

+0

更新了答案。该值不需要扩展,我们只需要将其定义内联(除非源文件包含它们自己的'source')。在这种情况下,为什么远程和本地有区别?例如。你可以使用'ssh user @ host -t“bash -x -c'echo hi'”' – dimid