【发布时间】:2020-08-21 22:41:20
【问题描述】:
我需要从带有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 中没有原始字符串机制之类的东西,我如何通过不转义单引号(即')等字符来正确解析正则表达式?
是否可以进行参数扩展?我尝试了这些都是徒劳的:
- P 标志(即 espace 序列替换)
- g:c(带有连接选项的进程转义序列)
- e 标志(执行单字外壳扩展)
还是使用通配符?或者可能带有子字符串修饰符?
编辑: 你让我今天一整天都感觉很好。感谢 user1934428 和 chepner 的好意。
【问题讨论】:
-
当你用
set -x运行它时,你应该看到dpkg|grep产生了什么。顺便说一句,虽然可能与问题无关,但您可以更轻松地将测试编写为if dpkg -s jq | grep -qF 'install ok installed'; then ....。实际上,你只需要知道 grep 是否找到了模式;无需使用[[ ... ]]并测试字符串是否存在。
标签: regex zsh glob anonymous-function rawstring