shell 脚本 (macOS):从 plist 字符串中打印转义的 Unicode 字符

Posted

技术标签:

【中文标题】shell 脚本 (macOS):从 plist 字符串中打印转义的 Unicode 字符【英文标题】:shell script (macOS): print escaped Unicode character from a plist string 【发布时间】:2017-03-17 15:22:14 【问题描述】:

在一个 shell 脚本中,我从应用程序包中的 Info.plist 中读取字符串,在本例中从版权键读取字符串,而 $FILEPATH 是应用程序包的路径,例如/Applications/TextEdit.app

#!/bin/bash  
PLIST=$(/usr/bin/defaults read "$FILEPATH/Contents/Info.plist")
COPYRIGHT=$(echo "$PLIST" | /usr/bin/awk -F" = " '/NSHumanReadableCopyright/print $2' RS=';' | /usr/bin/sed 's/^"\(.*\)"$/\1/')
echo "Copyright: $COPYRIGHT"

注意:我不是直接读取密钥,这当然更容易;它被读入变量 PLIST,因此脚本稍后也可以读取其他键,并且不必一遍又一遍地使用 defaults 命令。

现在输出是(例如)Copyright: Copyright \\U00a9 1995-2015, Apple Inc.\\nAll rights reserved.

显然版权符号 \U00a9 被转义了,换行符也是如此,但是我怎样才能解决这个问题,以便 shell 脚本实际打印出字符串,即使用版权符号和换行符?

PS:最后我可能会删除换行符,但作为第一步,我想按预期回显整个内容。

【问题讨论】:

【参考方案1】:

我会使用plutil 而不是defaults。该:

plist="/Applications/TextEdit.app/Contents/Info.plist"
plutil -p - < "$plist"

将打印

... some lines deleted...
  "DTSDKName" => "macosx10.12internal"
  "DTXcode" => "0800"
  "NSHumanReadableCopyright" => "Copyright © 1995-2016, Apple Inc.
All rights reserved."
  "DTSDKBuild" => "16C7"
  "CFBundleDevelopmentRegion" => "English"
... other delted lines ...

-p 的意思是 人类可读的格式 - 很难处理。因此,最好将plist 转换为json,例如:

plutil -convert json -r -o - - < "$plist"

-r 的意思是转换为人类可读的JSON,例如


  "CFBundleName" : "TextEdit",
  "DTSDKName" : "macosx10.12internal",
  "DTXcode" : "0800",
  "NSHumanReadableCopyright" : "Copyright © 1995-2016, Apple Inc.\nAll rights reserved.",
  "DTSDKBuild" : "16C7",
  "CFBundleDevelopmentRegion" : "English",
  "CFBundleVersion" : "329",

现在您可以轻松过滤掉NSHumanReadableCopyright 键,即使使用awk,但最好使用一些真正的 工具。

Mac 默认安装了perlJSON::PP 模块。所以:

plist="/Applications/TextEdit.app/Contents/Info.plist"
plutil -convert json -r -o - - < "$plist" |\
/usr/bin/perl -0777 -CSDA -MJSON::PP -MEncode -E '$p=decode_json(encode_utf8(<>));say $p->NSHumanReadableCopyright'

会输出

Copyright © 1995-2016, Apple Inc.
All rights reserved.

编辑: 将整个测试作为评论中的一长行:

plist="/Applications/TextEdit.app/Contents/Info.plist"; jplist=$(/usr/bin/plutil -convert json -r -o - "$plist"); copyright=$(echo "$jplist" | /usr/bin/perl -0777 -CSDA -MJSON::PP -MEncode -E '$p=decode_json(encode_utf8(<>));say $p->NSHumanReadableCopyright'); echo "$copyright"

然后打印OK...

【讨论】:

我可能建议引用"/Applications/TextEdit.app/Contents/Info.plist"(以防在处理其他应用程序名称时可能有空格,或者如果 $plist 变量没有碰巧是)。 效果很好。谢谢你。然而,不起作用的是将 JSON plutil 输出放入一个变量中,比如 jplist,然后将其回显并将其传递给 perl 命令。 jplist=$(/usr/bin/plutil -convert json -r -o - "$plist") ; copyright=$(echo "$jplist" | /usr/bin/perl -0777 -CSDA -MJSON::PP -MEncode -E '$p=decode_json(encode_utf8(&lt;&gt;));say $p-&gt;NSHumanReadableCopyright') ; echo "$copyright" (这没什么大不了的,因为 plutil + perl 本身似乎已经足够快了。) 不,实际上我现在测试了它,使用 plutil + perl 分别为每个键读取大量 plist 键,与单个默认值 read + echo & awk 相比,它非常慢。所以 plutil + perl 组合只适用于可能对标准输出造成问题的特定键。 啊,没有刷新并查看编辑...现在将对其进行测试。谢谢。 @JayB - 每一个键是什么意思?你在做别的事情。 JSON 是标准化格式。我回答了关于版权的问题——如果你想做其他事情——问一个新问题。 :)

以上是关于shell 脚本 (macOS):从 plist 字符串中打印转义的 Unicode 字符的主要内容,如果未能解决你的问题,请参考以下文章

防止/禁止 macOS 在 shell 脚本运行时关闭

macos shell脚本不返回控制

Xcode 10 构建阶段 Shell 脚本

如何在 macOS Catalina 的应用程序包中运行 shell 脚本

MacOS X:删除应用程序时删除 plist 文件

使用 electron-builder 向 macOS info.plist 添加协议的正确方法是啥?