如何将原始字符串传递给Zsh中的变量?

问题描述 投票:0回答:1

无论是否未安装前者,我都需要使用jqgrep从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标志(执行单个单词的shell扩展)

或带有限定符?也许还有子字符串修饰符?

编辑:你让我今天一整天都感觉很好。非常感谢user1934428和chepner的好意。

regex zsh glob anonymous-function rawstring
1个回答
0
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.