无论是否未安装前者,我都需要使用jq
或grep
从JSON文件中获取与“版本”键关联的值。我正在使用Zsh 5.7.1。
JSON文件看起来像这样;
{
"version": "1.7.0+01e7dgc6",
"date": "2020-04-06",
}
因此,预期结果是:
1.7.0+01e7dgc6
这是我的带有条件测试的脚本,它们提供一个正则表达式,该正则表达式又传递给匿名函数的位置参数:
#!/usr/bin/env zsh
# Fetch silently JSON latest numeroted version with `jq` if installed; fallback to `grep` otherwise.
set -x
if dpkg -s 'jq' | grep -qF 'install ok installed'; then
print "using jq"
API="jq -r '.master.version'"
else
print "falling back to grep"
API="grep -Po '(?<="version": "\)\[\^"]*'"
fi
function {
local JSON='path/to/URL/index.json'
curl -fsSL "$JSON" | $@
} ${API}
上面的脚本返回以下错误(在调试模式下:)
+(anon):2> curl -fsSL path/to/the/URL/index.json
+(anon):2> 'jq -r '\''.master.version'\'
(anon):2: command not found: 'jq -r '.master.version'
curl: (23) Failed writing body (0 != 9320)
您可以看到找不到该命令,因为正则表达式已由espace序列字符(即'jq -r'\''。master.version'\')解释。这就是为什么我需要原始字符串将正则表达式正确解析为位置参数的原因。
当测试失败时,肯定会出现相同的错误:
falling back to grep
+dpkg.zsh:9> API='grep -Po '\''(?<=version: )[^]*'\'
...
+(anon):2> 'grep -Po '\''(?<=version: )[^]*'\'
(anon):2: command not found: grep -Po '(?<=version: )[^]*'
curl: (23) Failed writing body (0 != 9320)
我如何通过不转义单引号(即'
)之类的字符来正确解析正则表达式,因为Z Shell中没有原始字符串机制?
可以通过参数扩展吗?我徒劳地尝试了这些:
或带有限定符?也许还有子字符串修饰符?
编辑:你让我今天一整天都感觉很好。非常感谢user1934428和chepner的好意。
zsh
在默认情况下不会对参数扩展执行单词拆分(并且依赖它反而容易出错),因此您要将single参数jq -r .master.version
传递给匿名函数,而不是3个参数jq
,-r
和.master.version
。请改用数组。
#!/usr/bin/env zsh
# Fetch silently JSON latest numeroted version with `jq` if installed; fallback to `grep` otherwise.
if dpkg -s 'jq' | grep -qF 'install ok installed'; then
print "using jq"
API=(jq -r '.master.version')
else
print "falling back to grep"
API=(grep -Po '(?<="version": "\)\[\^"]*')
fi
function {
local JSON='unified_resource_identifier/index.json'
curl -fsSL "$JSON" | "$@"
} $API # or "${API[@]}"
此外,使用whence
来查看jq
是否完全可用,而不是检查它是否专门与dpkg
一起安装。
if whence jq > /dev/null; then
API=(jq -r '.master.version')
else
API=(grep -Po '(?<="version": "\)\[\^"]*')
fi