Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 不使用';";“污染”;环境?_Bash_Shell - Fatal编程技术网

Bash 不使用';";“污染”;环境?

Bash 不使用';";“污染”;环境?,bash,shell,Bash,Shell,考虑以下两个脚本: envSetter.sh: #!/bin/bash export ENV_VAR=6 return 3 sourceable.sh: #!/bin/bash function main() { local var=5 source envSetter.sh } main "$@" unset -f main envSetter.sh是一个脚本,用于设置一些变量(并可能执行影响当前shell(环境)的其他操作)。我需要创建一个可源

考虑以下两个脚本:

envSetter.sh:

#!/bin/bash

export ENV_VAR=6
return 3
sourceable.sh:

#!/bin/bash

function main()
{
    local var=5
    source envSetter.sh
}

main "$@"

unset -f main
envSetter.sh
是一个脚本,用于设置一些变量(并可能执行影响当前shell(环境)的其他操作)。我需要创建一个可源代码的脚本,该脚本将源代码
envSetter.sh
,但也会在自身完成后进行清理。即,在运行
sourceable.sh
之后,我希望我的shell设置
ENV_VAR
,但我不希望定义
main
(或
sourceable.sh
使用的任何其他内容)

上面的脚本实现了这一点。然而,最重要的是,我希望
sourceable.sh
能够返回退出代码
main
返回的任何内容。现在,脚本返回
unset-f main
的结果。如果我删除该命令,我的脚本将保留我不希望定义的
main
函数。如果我尝试使用临时变量:

main "$@"
result=$?

unset -f main

return $result
它将返回我期望的结果,但也将保留我不想要的已定义的
result
。我也不能使用
main
函数并将所有代码放在脚本的顶层,但这会暴露
main
内部的更多垃圾(例如
local var
),这也是我不想要的


有没有办法将
envSetter.sh
(即,让它在当前shell中设置变量),返回
main
返回的内容,而不使用
sourceable.sh
使用的内容“污染”我的当前shell?澄清一下:我希望
envSetter.sh
影响我当前的shell,但我不希望
sourceable.sh
影响。

如何将
unset
命令隐藏在
main
函数中?像这样:

#!/bin/bash

main() {
    unset -f main
    local var=5
    source envSetter.sh
}

main "$@"
请注意,返回状态只会在中传播,因为
source envSetter.sh
main
中的最后一个命令,它将成为
main
的返回状态,同样,因为
main
是脚本中的最后一个命令,它将成为脚本的返回状态

顺便说一句,在本应与
源代码一起运行的东西上使用shebang没有多大意义。我倾向于使用这样的东西:

#!/bin/echo Run this script with the source or . command.

在返回陷阱中进行清理:

#!/bin/bash

trap 'unset -f main' RETURN

main()
{
    local var=5
    source envSetter.sh
}

main "$@"

您可以在子shell中获取脚本的源代码,并以可获取源代码的形式将所需的相关内容输出到stdout。像这样:

tmp=$(
   var=5
   # silence stdout so that it does not affect what we want
   source envSetter.sh >&2
   # modify the environment if you want to
   unexport ENV_VAR
   env_var="$ENV_VAR" # for example rename
   # output the environment in a format you want
   declare -p env_var ENV_VAR
   # declare -f function1 function2 # for functions
   # or printf "%q" "$ENV_VAR"
   # or write it to a file printf "%s" "$ENV_VAR" > somefile
   # ie. save the state where you want to
)
ret=$?
# Load hand picked variables.
eval "$tmp"
echo "ENV_VAR=$ENV_VAR ret=$ret"

只是一个地下地狱
(source envSetter.sh}
?我也考虑过,但如果我使用subshell
envSetter.sh
将无法影响我当前的shell(例如set
ENV_VAR
)。你说的是
不是“污染”我的当前shell
,然后决定。您想手工选择想要的变量吗?如果我的意图不够明确,很抱歉。但是我指定了:“不要用任何
sourceable.sh
使用的东西“污染”我的当前shell”。源代码的退出代码只是源代码脚本中最后一个命令的退出代码。
main
函数的用途是什么?如果您只是源代码脚本,那么退出代码将保存在
$?
中。返回陷阱将保留在此之后,OP将不得不重置它。然后,返回陷阱-返回
在脚本中陷阱主体?@glennjackman这是我的一个想法,如果脚本是以交互方式来源的,它似乎是有效的。但是当从shell脚本来源时,它给出了一个语法错误。(
unset-f main
INSIDE
main
完成了这个技巧,谢谢!我甚至认为这样的事情是不允许的。)