简体   繁体   English

如果bash`declare var`失败,失败的更好方法是什么?

[英]better way to fail if bash `declare var` fails?

Problem 问题

In some bash scripts, I don't want to set -e . 在某些bash脚本中,我不想set -e So I write variable declarations like 所以我写像

var=$(false) || { echo 'var failed!' 1>&2 ; exit 1 ; }

which will print var failed! 这将打印var failed! .

But using declare , the || 但是使用declare|| is never taken. 从来没有采取。

declare var=$(false) || { echo 'var failed!' 1>&2 ; exit 1 ; }

That will not print var failed! 不会打印var failed! .

Imperfect Solution 不完善的解决方案

So I've come to using 所以我来使用

declare var=$(false)
[ -z "${var}" ] || { echo 'var failed!' 1>&2 ; exit 1 ; }

Does anyone know how to turn the Imperfect Solution two lines into a neat one line ? 有谁知道如何将不完美解决方案的两行变成整齐的一行? In other words, is there a bash idiom to make the declare var failure neater? 换句话说,是否有使bash declare var更整洁的bash习惯用法?

More Thoughts 更多想法

This seems like an unfortunate mistake in the design of bash declare . 这似乎是bash declare设计中的一个不幸错误。

Firstly, the issue of two lines vs. one line can be solved with a little thing called Mr. semicolon (also note the && vs. || ; pretty sure you meant the former): 首先,可以用一个叫分号的小东西解决两行和一行的问题(还要注意&& vs. || ;您确定是前者):

declare var=$(false); [ -z "${var}" ] && { echo 'var failed!' 1>&2 ; exit 1 ; }

But I think you're looking for a better way of detecting the error. 但我认为您正在寻找一种更好的检测错误的方法。 The problem is that declare always returns an error code based on whether it succeeded in parsing its options and carrying out the assignment. 问题在于, declare始终根据其是否成功解析其选项并执行分配来返回错误代码。 The error you're trying to detect is inside a command substitution, so it's outside the scope of declare 's return code design. 您尝试检测的错误在命令替换内,因此不在declare的返回码设计范围内。 Thus, I don't think there's any possible solution for your problem using declare with a command substitution on the RHS. 因此,我认为在RHS上使用带命令替换的declare没有任何可能的解决方案。 (Actually there are messy things you could do like redirecting error infomation to a flat file from inside the command substitution and reading it back in from your main code, but just no.) (实际上,您可以做一些杂乱的事情,例如将错误信息从命令替换内部重定向到平面文件,然后从您的主代码读回它,但没有。)

Instead, I'd suggest declaring all your variables in advance of assigning them from command substitutions. 相反,我建议在通过命令替换分配它们之前先声明所有变量。 In the initial declaration you can assign a default value, if you want. 如果需要,可以在初始声明中分配默认值。 This is how I normally do this kind of thing: 这通常是我做这种事情的方式:

declare -i rc=-1;
declare s='';
declare -i i=-1;
declare -a a=();

s=$(give me a string); rc=$?; if [[ $rc -ne 0 ]]; then echo "s [$rc]." >&2; exit 1; fi;
i=$(give me a number); rc=$?; if [[ $rc -ne 0 ]]; then echo "i [$rc]." >&2; exit 1; fi;
a=($(gimme an array)); rc=$?; if [[ $rc -ne 0 ]]; then echo "a [$rc]." >&2; exit 1; fi;

Edit: Ok, I thought of something that comes close to what you want, but if properly done, it would need to be two statements, and it's ugly, although elegant in a way. 编辑:好的,我想到的事情与您想要的很接近,但是如果正确完成,则需要两个语句,而且很丑,尽管在某种程度上很优雅。 And it would only work if the value you want to assign has no spaces or glob (pathname expansion) characters, which makes it quite limited. 而且只有在您要分配的值没有空格或glob(路径名扩展)字符的情况下才起作用,这使其受到很大限制。

The solution involves declaring the variable as an array, and having the command substitution print two words, the first of which being the actual value you want to assign, and the second being the return code of the command substitution. 解决方案包括将变量声明为数组,并让命令替换打印两个词,其中第一个是您要分配的实际值,第二个是命令替换的返回码。 You can then check index 1 afterward (in addition to $? , which can still be used to check the success of the actual declare call, although that shouldn't ever fail), and if success, use index 0, which elegantly can be accessed directly as a normal non-array variable can: 然后,您可以随后检查索引1(除了$?它仍然可以用于检查实际declare调用的成功,尽管那应该永远不会失败),如果成功,则使用索引0,可以优雅地使用作为普通的非数组变量直接访问可以:

declare -a y=($(echo value-for-y; false; echo $?;)); [[ $? -ne 0 || ${y[1]} -ne 0 ]] && { echo 'error!'; exit 1; }; ## fails, exits
## error!
declare -a y=($(echo value-for-y; true; echo $?;)); [[ $? -ne 0 || ${y[1]} -ne 0 ]] && { echo 'error!'; exit 1; }; ## succeeds
echo $y;
## value-for-y

I don't think you can do better than this. 我认为您不能做得更好。 I still recommend my original solution: declare separately from command substitution+assignment. 我仍然建议我使用原始解决方案:与命令替换+赋值分开声明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM