未定义的变量不会导致子shell退出,即使设置了 -eu。

10
$ cat test.sh
set -eu
echo "`wc -l < $DNE`"
echo should not get here

$ /bin/bash test.sh
test.sh: line 2: DNE: unbound variable

should not get here

我正在运行bash版本4.1.2。有没有办法确保所有这样在子shell中使用未绑定变量的用法都会导致脚本退出,而无需修改涉及子shell的每个调用?


@Phil的答案在Linux、OS X和Solaris上都有效。你可以考虑接受它。 - jww
1
这是一个不错的替代方案,但并没有解决原问题“无需修改每个调用”的要求。如果标志符按照预期工作,那么它比在特定情况下每次使用变量时都要记得做某些事情更加方便。 - Jason
2个回答

12

确保变量清洗的更好解决方案

#!/usr/bin/env bash

set -eu

if [[ ${1-} ]]; then
  DNE=$1
else
  echo "ERROR: Please enter a valid filename" 1>&2
  exit 1
fi

在花括号内插入连字符,就像这样的变量名称,可以使bash合理地处理未定义的变量。我还强烈建议查看Google shell风格指南,它是一个很好的参考https://google.github.io/styleguide/shell.xml

[[ -z ${variable-} ]] \
  && echo "ERROR: Unset variable \${variable}" \
  && exit 1 \
  || echo "INFO: Using variable (${variable})"

3

使用一个临时变量,以便让test.sh进程了解wc的失败情况。您可以将其更改为:

#!/bin/bash
set -eu
out=$(wc -l < $DNE)
echo $out
echo should not get here

现在,如果 wc 失败,您将不会看到 "should not get here"。

1
谢谢,但如果我总是能记得正确地做事,我根本不需要-eu选项来捕捉bash本来会放过的错误 :) 我正在寻找一种告诉bash在不改变所有代码-eu适用的情况下减少对错误的宽容度的方法。 - Jason
您需要检查每个命令的返回代码并打印适当的消息/错误处理。-e是一个选项,当希望在任何失败时退出时使用。Bash是一种解释性语言,因此这种乐趣只存在于编译语言中 :) 但它提供了合理的选项,如这里的-e。 - P.P
1
@AquariusPower -e 实际上是用于调试目的。它不提供任何有用的信息;它只是失败了。除此之外,检查错误的通常方法是使用变量 $? 来捕获返回代码。 - P.P
我只想让代码在遇到"未绑定的变量"这个错误时自动退出,因为其他所有的错误我都会手动处理;也许提一个新问题会很酷? :) - Aquarius Power
如果您只关心未设置的变量被使用,那么您可以执行以下操作:set -o nounset - P.P
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接