我想要一个 bash 脚本,它允许我调用一个函数来查看文件中是否包含某些数据,如果它没有使主脚本失败,类似于以下内容,简化为保留这一点。
这不起作用(当子 shell 失败时不退出主脚本)。
我该如何编写require_line
函数,这样我就可以像这样在一个文件中说出其中的 20 多个
VALUE1=$(require_line "myKey1")
VALUE2=$(require_line "myKey2")
...
并且不需要一个 if 围绕每个?
#!/bin/bash
set -eo pipefail
VALUE=$(require_line "myKey")
require_line(){
local KEY=$1
local DATA=$(cat /tmp/myfile)
local INFO=$(echo "$DATA" | grep "$KEY")
if [ ! -z "$INFO" ]
then
echo "Key not found in $DATA, key: $KEY"
exit 1;
fi
echo "$INFO"
}
require_line
让我们稍微重构一下你的脚本来帮助你。首先,我们可以摆脱无用的
cat | grep
. 其次,我们可以使用grep
' 的内在行为来指示搜索的成功或失败KEY
,以及将密钥(如果找到)打印到stdout
。这利用了
grep
. 如果找到密钥,则grep
打印匹配行并返回成功。否则,将采用else
分支,并打印一条消息,指示未找到密钥。此外,在grep
失败的情况下,将打印错误消息,stderr
以便错误消息不会被误认为是在$FILE
.您可以进一步修改
require_line
以接受文件名作为$2
参数,方法是更改要读取的行local FILE="$2"
,然后在每次调用时传递所需的文件名require_line
。现在,有了它....
您真的需要为 KEYn 存储每个 VALUEn,还是只需要确保它们都存在?
既然您有一个
require_line
干净地返回成功或失败值的函数,您可以简单地AND
将所有测试放在一起。只要其中任何一个失败,整个测试就会失败。假设您确实需要实际的匹配值,那么冗长的方法是:
如果您有许多要检查的键,那将变得乏味。使用数组可能会更好:
使用一些示例数据运行该代码:
最后,如果您真的只需要验证所有键是否存在而不需要知道匹配值是什么,则可以将上面面向数组的代码简化为简单地循环直到找到所有键,或者在第一个键处中止发现丢失了。
退出 subshell 不会像您经历的那样退出主脚本。
我想到了 3 个(半个)解决方案:
set -e
这样任何(“未经测试”)失败的命令(或子shell)将立即退出主脚本(这可能是矫枉过正或导致其他麻烦),trap
|| exit $?
每次VALUEn=$(...)
像这样使用VALUE=$(require_line "myKey") || exit $?
,eval
。第三个并不完全“需要一个 if 围绕每个”,并且仍然是一个相当紧凑的语法恕我直言。
顺便说一句,这条线
...如果您在此之后立即退出整个脚本,实际上是无用的,因为该句子将存储在
$VALUEn
不会显示的变量中。我建议打印成
stderr
这样:例子
解决方案 1 的示例
但是,如果我
set -e
从一开始就删除,我会得到:解决方案 2 的示例
解决方案 3 的示例
解决方案 4 的示例