我相信这是一个引用和变量范围问题

我相信这是一个引用和变量范围问题

以下是推荐的解决方案。我运行了它并且它有效。

#!/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_nametrap 参数的求值,则需要用单引号传递。

#!/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

相关内容