以下是推荐的解决方案。我运行了它并且它有效。
#!/bin/bash
function exit_handler() {
local device_name="${1}"
echo "Exit handler: ${device_name}"
}
function other() {
echo "Other: ${device_name}"
}
function do_something() {
local device_name="abc"
trap "exit_handler '${device_name}'" EXIT
other
}
do_something
# (my comment) I am assuming an implied exit here
我实际上在添加注释的命令行中输入了真正的退出到终端
鉴于以下问题,我不明白什么以及为什么它有效:
问题一——给出:
trap "exit_handler '${device_name}'" EXIT
${device_name} 周围的单引号表明(无论如何对我来说)应该在启动陷阱时进行替换(在处理退出之后,这将在“do_something”返回之后并且局部变量 ${device_name} 不再存在,在我看来),因为代码中没有 exit 语句,也没有明显的错误原因导致退出。函数“do_something”应该已返回,并且不应再存在变量 ${device_name} 来满足替换。如果该语句在没有单引号的情况下重新编码为
trap "exit_handler ${device_name}" EXIT
我清楚地看到当 trap 语句在退出发生之前很长时间执行时,替换是如何发生的。我不明白这里的 bash 引用是什么?
问题二——给出“do_something”中的以下语句:
other
是否有一些特殊的作用域规则允许 ${device_name} 的本地值可用于从“do_something”调用的函数“other”,当它被认为是“do-nothing”的本地值并且“other”显然不是“do_something”的本地值时'做一点事'?我相信其他语言的范围规则会阻止这种情况。要求函数调用(如陷阱调用)需要 ${device_name} 作为参数,如下所示
other "${device_name}"
和“其他”需要将参数分配给局部变量
local device_name="${1}"
显然,我不明白 Bash 中的作用域。
答案1
当你执行这段代码时,
local device_name="abc" trap "exit_handler '${device_name}'" EXIT
shell 会看到双引号并计算$()
其中的变量和表达式:
device_name="abc"
trap "exit_handler 'abc'" EXIT
然后 shell 执行结果,从而设置退出陷阱。当(如果)陷阱触发时,exit_handler
将使用单个三字符参数调用该函数abc
。
你的声明,“${device_name} 周围的单引号表明(无论如何对我来说)应该在启动陷阱时进行替换" 是不正确的。整个表达式周围的双引号控制 shell 看到和计算的内容。此时字符串内的单引号只是普通字符。
如果您想要延迟对$device_name
trap 参数的求值,则需要用单引号传递。
#!/bin/bash
exit_handler() {
local device_name="$1"
echo "Exit handler: $device_name"
}
other() {
echo "Other: $device_name"
}
do_something() {
local device_name="abc"
trap 'exit_handler "$device_name"' EXIT
other
}
do_something