typeset -f 不输出真正的定义。可以检测/修复吗?

typeset -f 不输出真正的定义。可以检测/修复吗?

昨天我花了大半时间才发现这个 bug 存在于 Bash 中。

outer () 
{ 
    function inner () 
    { 
        cat <<_EOS
foo
_EOS
    }
    inner
}

将显示为typeset -f outer

outer () 
{ 
    function inner () 
    { 
        cat <<_EOS
    }
foo
_EOS
    inner
}

这显然不一样。在 CygWin (bash 4.4.12) 中,输出以不同的方式出现错误:

outer ()
{
    function inner ()
    {
        cat
    } <<_EOS
foo
_EOS

    inner
}

该错误已在较新版本的 Bash 中修复。

我用这个来env_parallel.env_parallel取决于输出是否typeset -f正确。

这是一个极端情况的错误,所以我真的不想env_parallel发出警告,除非确实存在影响结果的风险。另一方面,如果存在真正的风险,我希望得到警告,因为我真的不希望用户像昨天一样沮丧。

如果 bug 存在于 的输出中,是否可以可靠地检测到typeset -f?不写bash解析器可以纠正它吗?

答案1

您可以检查某些代码在语法上是否有效:

if bash -O extglob -n < some-code 2> /dev/null; then
  echo that seems valid
fi

但请注意,语法可能会受到别名、区域设置(LC_CTYPE 类别)和 bash 中的extglob选项的影响。

例如,一段代码在使用 on 时可能有效,extglob但在不使用时则无效(例如echo @(x)),通常反之亦然,因此最好使用extglobon 检查语法。

一段代码可能在一个语言环境中有效,但在另一个语言环境中无效($'\xe9=(x)'在该语言环境中有效fr_FR.iso88591,但在 UTF-8 语言环境或 C 语言环境中无效),就像变量名中有效的字符一样(也可以作为标记分隔符! ) 取决于语言环境(因此,将 的输出提供typeset -f给另一个版本不同或不在同一系统上的同一语言环境中运行的 bash 调用通常也是危险的)。

alias forever='while true; do'
forever echo test; done

会被 报告为无效bash -n,但不会被 报告为无效bash -O expand_aliases,因为一旦alias运行该命令,第二行就变得有效。但在检查输出的语法时这不是问题typeset -f

在这里,您可以使用它来检测由该错误或其他错误引起的语法错误,但由于上述考虑因素,它并不是万无一失的,而且还因为该错误仍然可能意外生成有效代码。

相关内容