如何在bash中执行Perl动态生成的bash脚本代码?
解决方案
核心原因说明
你之前的第一种写法无法生效,是因为Bash的$()命令替换只会将输出内容拆分为命令参数,不会解析其中的Shell元字符(分号、换行、循环关键字、重定向符等都只会被当做普通字符串处理),因此ls -ltr;pwd会被识别为ls的第一个参数,自然会报错找不到该文件。
可用实现方案
方案1:使用eval直接解析Perl输出的脚本内容(推荐,单行实现,可作用于当前Shell)
将Perl的输出全部传给eval,Bash会将其作为完整的Shell脚本语法解析,完全支持分号、换行、循环、环境变量修改等所有Bash特性,且不会创建多余的子Shell:
eval "$(perl -e 'print "ls -ltr;pwd"')"
支持复杂Bash逻辑的示例:
# 执行后环境变量、工作目录修改都会在当前Shell生效 eval "$(perl -e 'print "export MY_TEST=123 cd /tmp pwd for i in 1 2 3; do echo 循环值:\$i done "')" # 执行后 echo $MY_TEST 会输出123,当前目录也会切换到/tmp
方案2:使用管道传给Bash执行(适用于不需要修改当前Shell环境的场景)
如果生成的脚本不需要修改当前Shell的环境变量、工作目录,直接将Perl输出通过管道传给Bash执行即可:
perl -e 'print "ls -ltr\npwd\nfor i in a b c; do echo \$i; done"' | bash
方案3:使用进程替换+source(同方案1效果,可读性更好)
如果你的Bash版本支持进程替换(绝大多数现代Bash都支持),也可以用以下写法,逻辑更清晰:
source <(perl -e 'print "ls -ltr export MYVAR=test pwd "')
方案对比
eval和source+进程替换都是在当前Shell执行生成的代码,支持修改当前Shell的环境变量、工作目录,符合你的需求- 管道传给Bash的方式在子Shell中执行,生成的脚本中所有环境修改都不会影响外层的主Shell
- 完全不需要创建临时文件,都是内存中执行,性能远高于你提到的临时文件方案
内容的提问来源于stack exchange,提问作者Siegfried
相关产品推荐
相关产品推荐

