无法在函数中运行命令(shell脚本)

发布于 2025-02-04 11:30:25 字数 634 浏览 3 评论 0原文

我在〜/.zshrc

async () {
    if ! [[ $# -gt 0 ]];then
        echo "Not enough arguments!"
    fi
    local busus="$IFS"
    export IFS=" "
    echo "$* &"
    command "$* &"
    export IFS="$busus"
}

和一个别名

alias word='async "libreoffice --writer"'

echo“ $*&“ line仅用于调试)中。 当我运行Word时,libreoffice -writer&在屏幕上显示(没有额外的空格或新线),但什么也不会发生。 我还尝试执行命令libreoffice -writer&,它效果很好。 (我目前的外壳是ZSH) 怎么了?

谢谢

I have this function in my ~/.zshrc

async () {
    if ! [[ $# -gt 0 ]];then
        echo "Not enough arguments!"
    fi
    local busus="$IFS"
    export IFS=" "
    echo "$* &"
    command "$* &"
    export IFS="$busus"
}

and an alias

alias word='async "libreoffice --writer"'

The echo "$* &" line is used only for debugging.
When I run word, libreoffice --writer & is shown on the screen (no extra spaces or newlines), but nothing happens.
I also tried executing command libreoffice --writer & and it worked perfectly.
(My current shell is zsh)
What is wrong?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

如梦 2025-02-11 11:30:25

通常(尤其是在狂欢中),问题是人们没有使用足够的双引号。在这种情况下,情况恰恰相反:您使用的是过多的双报价。基本问题是,命令名称和每个参数必须是一个单独的“单词”(在shell语法中),但是双引号(通常)将(通常)将shell视为一个单词。这是一个快速演示:

% echo foo
foo
% "echo foo"
zsh: command not found: echo foo

在这里,双引号使shell对待“ foo”作为命令名称的一部分,而不是作为命令名称之后的定界符和参数。同样,当您使用“ $*&“)时,双引号告诉shell将整个事物(包括andand)视为一个长词(并将其作为参数传递给命令)。 (顺便说一句,不需要命令,但也不需要造成任何伤害。)

这样做的标准方法是使用“ $@” -在这里,$@在双重引用中特别行动,将每个参数变成一个单独的单词。在ZSH中,您可以省略双引号,但这可能会在其他外壳中造成麻烦,因此我建议无论如何都会使用它们。

另外,不要与ifs混乱。您不需要,它打开了一罐蠕虫,最好是左关闭。如果没有参数,则应立即返回,而不是继续并尝试运行一个空命令。

但是还有另一个问题:在别名中,您double-Quote “ libreoffice-writer”,它将再次具有相同的效果。因此,请删除那些双重报价。但是,请将单点引用在别名周围,因此将其定义为单个别名。

因此,这是我建议的更正:

async () {
    if ! [[ $# -gt 0 ]];then
        echo "Not enough arguments!"
        return 1    # Do not continue if there's no command to run!
    fi
    echo "$* &"    # Here quoting is appropriate, so it's a single argument to echo
    "$@" &
}

alias word='async libreoffice --writer'

Usually (especially in bash), the problem is that people aren't using enough double-quotes; in this case, it's the opposite: you're using too many double-quotes. The basic problem is that the command name and each of the arguments to it must be a separate "word" (in shell syntax), but double-quoting something will (usually) make the shell treat it as all one word. Here's a quick demo:

% echo foo
foo
% "echo foo"
zsh: command not found: echo foo

Here, the double-quotes make the shell treat " foo" as part of the command name, rather than as a delimiter and an argument after the command name. Similarly, when you use "$* &", the double-quotes tell the shell to treat the entire thing (including even the ampersand) as a single long word (and pass it as an argument to command). (BTW, the command isn't needed, but isn't causing any harm either.)

The standard way to do this is to use "$@" instead -- here the $@ acts specially within double-quotes, making each argument into a separate word. In zsh, you could omit the double-quotes, but that can cause trouble in other shells so I recommend using them anyway.

Also, don't mess with IFS. You don't need to, and it opens a can of worms that's best left closed. And if there are no arguments, you should return immediately, rather than continuing and trying to run an empty command.

But there's another problem: in the alias, you double-quote "libreoffice --writer", which is going to have pretty much the same effect again. So remove those double-quotes. But keep the single-quotes around the alias, so it'll be defined as a single alias.

So here's my proposed correction:

async () {
    if ! [[ $# -gt 0 ]];then
        echo "Not enough arguments!"
        return 1    # Do not continue if there's no command to run!
    fi
    echo "$* &"    # Here quoting is appropriate, so it's a single argument to echo
    "$@" &
}

alias word='async libreoffice --writer'
从此见与不见 2025-02-11 11:30:25

直接使用“ $@”更可靠:

async () { [ "$#" -gt 0 ] && "$@" & }

alias word='async libreoffice --writer'

Using "$@" directly is more reliable:

async () { [ "$#" -gt 0 ] && "$@" & }

alias word='async libreoffice --writer'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文