使用函数而不是别名在zsh中会误解参数。

huangapple go评论54阅读模式
英文:

Using function instead alias misunderstands argument in zsh

问题

**问题**

我想将一个已经存在的别名更改为一个具有指定参数的函数。

原始代码:

```bash
# support Compose v2 as docker CLI plugin
(( ${+commands[docker-compose]} )) && dccmd='docker-compose' || dccmd='docker compose'
...
alias dcdn="$dccmd down"
...

我想要实现的:

# support Compose v2 as docker CLI plugin
(( ${+commands[docker-compose]} )) && dccmd='docker-compose' || dccmd='docker compose'

dcdn() {
    if [ "$1" != "" ]
    then
        '$dccmd -f "$1" down'
    else
        "$dccmd down"
    fi
}

我的期望

当我执行 dcdn 时,期望的结果是 docker-compose down,如果我执行 dcdn docker-compose-dev.yml,则应该运行 docker-compose -f docker-compose-dev.yml down

而实际上我得到的结果是 ''« down» 命令未找到''。

我尝试过的事情

我尝试了几种其他方法,但都没有成功,只是得到相同的错误或奇怪的“权限被拒绝”:

'$dccmd down'           # $dccmd down not found
"dccmd down"            # $dccmd down not found
"$aliases[dccmd] down"  # «down» not found
"$dccmd" down           # permission denied
'$dccmd' down           # $dccmd not found
$dccmd down             # «down» not found
dccmd down              # «dccmd» not found

我甚至尝试了一些使用 eval 的选项,但结果仍然相同。

如果我直接使用 docker-compose down,它可以正常工作,但那时我没有使用 dccmd 中存储的命令。

注意:我在其他帖子中看到“权限被拒绝”的原因可能是 dccmd 为空,但是为什么别名可以工作呢?


<details>
<summary>英文:</summary>

**The problem**

I want to change an already existing alias into a function to specify an argument.

The original code:

    # support Compose v2 as docker CLI plugin
    (( ${+commands[docker-compose]} )) &amp;&amp; dccmd=&#39;docker-compose&#39; || dccmd=&#39;docker compose&#39;
    ...
    alias dcdn=&quot;$dccmd down&quot;
    ...

What I want to achieve:

    # support Compose v2 as docker CLI plugin
    (( ${+commands[docker-compose]} )) &amp;&amp; dccmd=&#39;docker-compose&#39; || dccmd=&#39;docker compose&#39;
    
    dcdn() {
        if [ &quot;$1&quot; != &quot;&quot; ]
        then
            &#39;$dccmd -f &quot;$1&quot; down&#39;
        else
            &quot;$dccmd down&quot;
        fi
    }

**What I expect**

Then when I execute `dcdn` the result expected is `docker-compose down` and if I execute `dcdn docker-compose-dev.yml` it should runs `docker-compose -f docker-compose-dev.yml down`.

Instead the result I get is &#39;&#171; down&#187; command not found&#39;.

**Things I&#39;ve tried**

I tried several other ways and nothing work, just givin same error or a strange &quot;permission denied&quot;:

'$dccmd down' # $dccmd down not found
"dccmd down" # $dccmd down not found
"$aliases[dccmd] down" # «down» not found
"$dccmd" down # permission denied
'$dccmd' down # $dccmd not found
$dccmd down # «down» not found
dccmd down # «dccmd» not found


I even tried a few options with eval with same results.

If I use `docker-compose down` directly it works, but then I&#39;m not using the command stored in dccmd.

NOTE: I saw in other posts that the permission denied could be because dccmd is &quot;&quot; but then why the alias works?

</details>


# 答案1
**得分**: 2

你的引用不正确。你不想要将命令及其所有参数放在一个单一的 shell 单词中,这正是引用整个命令所实现的。

```bash
dcdn () {
    if [ -n "$1" ]
    then
        "$dccmd" -f "$1" down
    else
        "$dccmd" down
    fi
}

然而,这依然不会工作,原因类似:如果你设置 dccmd="docker compose",现在 "$dccmd" 展开不是两个单词,一个命令和它的第一个参数,而是一个包含空格的单词,而字符串 docker compose 不是一个命令的名称。

解决方案是定义另一个函数,而不是一个参数。

if (( ${+commands[docker-compose]} )); then
    dccmd () { docker-compose "$@" }
else
    dccmd () { docker compose "$@" }
fi

dcdn () {
    if [ -n "$1" ]
    then
        dccmd -f "$1" down
    else
        dccmd down
    fi
}
英文:

Your quoting is incorrect. You don't want the command and all its arguments in a single shell word, which is what quoting the entire command accomplishes.

dcdn () {
    if [ -n &quot;$1&quot; ]
    then
        &quot;$dccmd&quot; -f &quot;$1&quot; down
    else
        &quot;$dccmd&quot; down
    fi
}

This still won't work, though for a similar reason: if you set dccmd=&quot;docker compose&quot;, now &quot;$dccmd&quot; expands not to two words, a command and its first argument, but to a single word that contains a space, and the string docker compose is not the name of a command.

The solution is to define another function, not a parameter.

if (( ${+commands[docker-compose]} )); then
    dccmd () { docker-compose &quot;$@&quot; }
else
    dccmd () { docker compose &quot;$@&quot; }
fi


dcdn () {
    if [ -n &quot;$1&quot; ]
    then
        dccmd -f &quot;$1&quot; down
    else
        dccmd down
    fi
}

huangapple
  • 本文由 发表于 2023年3月4日 02:25:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75630636.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定