bash - plistbuddy - 如何拦截错误( key 不存在)

标签 bash error-handling

我正在使用 plistbuddy 读取一个 plist 文件;我正在从不同的词典中收集数据。

问题是有时值不存在,出于某种原因,所以我得到输出 "Key does not exist"

有没有办法拦截它,这样,如果该值不存在,我可以用 0 或其他值替换它?

我使用 shell 脚本;我想使用一个简单的 if ... else 语句,试图检查字符串 "key does not exist",但它不起作用(我从来没有点击true 条件下,我假设消息只是发送到标准输出,而不是保存在我的变量中)。

文档没有太大帮助,所以我被卡住了。

因为我计算的是平均值,一个错误打乱了我的计算,这就是为什么我想加一个 0,这样我可以稍后检查是否有 0 并更改函数以相应地计算平均值。

基本上这是我的代码示例:(filename 是 plist 文件名)

for i in {0..3}
do
    TempValue=$(/usr/libexec/PlistBuddy -c "print :process:$i:testname:result" $fileName)
    echo $TempValue
    Data_results+=($TempValue)
done 

# Calculate Average
tmpResult=`echo ${Data_results[0]} + ${Data_results[1]} + ${Data_results[2]} + ${Data_results[3]}|bc`
AverageTime=$(bc <<< "scale=10; $tmpResult / 4")  
echo "average for test name: " $AverageValue

谢谢!

最佳答案

macOS /usr/libexec/PlistBuddy 实用程序是一个运行良好的 CLI:

  • 如果成功,它的退出代码是0
  • 在失败的情况下,它的退出代码是非零的
  • 它的常规输出被发送到stdout,错误信息被发送到stderr

有多种方法可以检查是否成功;例如:

# Query and save the value; suppress any error message, if key not found.
val=$(/usr/libexec/PlistBuddy -c 'print ":SomeKey"' file 2>/dev/null)

# Save the exit code, which indicates success v. failure
exitCode=$? 

if (( exitCode == 0 )) then # OK
   # handle success ....
else
   # handle failure ...
fi

更新 1

这是您的特定用例的片段;您可以按原样运行它以查看它是如何工作的(它使用 Finder 存储其首选项的 Plist 文件):

# Loop over keys and retrieve the corresponding values.
# If the key doesn't exist, assign '0'.
for key in ':AppleShowAllFiles' ':NoSuchKey'; do
    val=$(/usr/libexec/PlistBuddy -c "print \"$key\"" \
          ~/Library/Preferences/com.apple.finder.plist 2>/dev/null || printf '0')
    echo "Value retrieved: [$val]"
done

如您所见,对于第二个不存在的 key ,$val 将包含 0

2>/dev/null 重定向抑制 stderr 输出(错误消息),|| 运算符用于提供替代命令以创建输出,以防万一调用 PlistBuddy 表示失败(通过其退出代码)。

唯一需要注意的是,您无法将不存在的 key 与更根本的故障区分开来,例如不存在或损坏的 Plist 文件。处理会更加复杂,因为 PlistBuddy 不使用不同的退出代码来区分这些情况。


更新 2

这是您的代码的简化版本,其中包括所需的默认为 0 逻辑:

# Collect temperatures.
Data_results=()
for i in {0..3}
do
    Data_results+=( $(/usr/libexec/PlistBuddy \
            -c "print :process:$i:testname:result" "$fileName" 2>/dev/null || 
            printf '0') )
done 

# Calculate average
AverageValue=$(bc <<< \
                "scale=10; $(( ${Data_results[@]/%/ +} 0 )) / ${#Data_results[@]}")  
echo "average for test name: " $AverageValue

注意:$(( ... )) 是一个算术展开式(仅限整数),它使用了一个小技巧来求和数组的元素:${Data_results[@ ]/%/+} + 附加到数组的每个元素。例如,(1 2 3) 的输入数组将扩展为 1 + 2 + 3 +;因为这留下了一个悬空的 +,我只是添加了另一个 0 来形成一个有效的表达式。 结合除以 ${#Data_results[@]} - 数组中的元素数量 - 该命令然后适用于任何大小的数组。

关于bash - plistbuddy - 如何拦截错误( key 不存在),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22852429/

相关文章:

bash - linux环境变量设置消失

linux - 从 root (unix) 运行脚本时变量不存储值

objective-c - Objective-C : Is it possible to see full error-path?

r - 基于算法进行预测时出错

c# - HtmlWindow.Error 事件不会因 Javascript 错误而触发

linux - Bash:按数字列加入

bash - 如何在 Bash 中写入二进制数据

python - Appengine错误未出现在日志中

bash - 如何在命令中使用文件并将输出重定向到同一文件而不截断它?

json - 处理IE且不处理fileSize等