【问题标题】:Command stored in variable isn't recognized as coomand on if sentence - Linux Bash Script存储在变量中的命令在 if 语句中不被识别为命令 - Linux Bash 脚本
【发布时间】:2022-01-04 11:47:25
【问题描述】:

我正在尝试制作一个简单的 bash 脚本来检查是否可以执行 ping 命令(有互联网),否则。

我已经有一个完美运行的代码,它直接在 if 语句中检查是否可以执行 ping 命令而不使用 /dev/null 进行输出。

旧代码:

#! /usr/bin/bash

YELLOW="\e[33m"
RED="\e[1;31m"
GREEN="\e[1;32m"
ENDCOLOR="\e[0m"

if ping -c 1 8.8.8.8 > /dev/null 2>&1; then
        echo -e "${YELLOW}[*]${ENDCOLOR} You have Internet access."
else
        echo -e "\n ${RED}[!]${ENDCOLOR} You don't have Internet access !"
        echo -e "\n ${YELLOW}[*]${ENDCOLOR} Quitting webDirDiscover..."
        exit 1
fi

现在我要做的是将命令 ping -c 1 8.8.8.8 存储在一个名为 PING 的变量中。完成后,执行 if 语句并检查结果。

问题是这样做会返回错误:

./webDirDiscover.sh: line 10: PING: command not found

当我认为 if 语句应该正常工作时。

当前代码:

#! /usr/bin/bash

YELLOW="\e[33m"
RED="\e[1;31m"
GREEN="\e[1;32m"
ENDCOLOR="\e[0m"

PING=$(ping -c 1 8.8.8.8)

if $PING -eq 0; then
        echo -e "${YELLOW}[*]${ENDCOLOR} You have Internet access."
else
        echo -e "\n ${RED}[!]${ENDCOLOR} You don't have Internet access !"
        echo -e "\n ${YELLOW}[*]${ENDCOLOR} Quitting webDirDiscover..."
        exit 1
fi

除了解决这个简单的脚本之外,这在执行更复杂的命令时会派上用场,从而获得更直观和视觉上令人愉悦的代码。

【问题讨论】:

  • 嗨。不要使用变量来保存命令;从技术角度来看,功能是恰当的解决方案。尽管如此,我还是会分享一个答案,解释为什么你的脚本不能按预期工作
  • 好的,不使用变量保存命令有什么具体原因吗?现在我下班了,所以不能用功能测试它。我什么时候可以试试!谢谢
  • 您没有将命令存储在变量中,而是将命令的输出存储到了变量中。另外,这样做有什么意义?如果你真的想通过一个变量来操作一个命令(例如,因为你想以一种你觉得在函数中太复杂的方式来摆弄参数),不要将它存储到一个标量中,而是一个数组(除非你喜欢调试噩梦)。当然,您可以为此目的误用变量,就像使用自行车搬运沉重的橡木桌子一样。

标签: bash shell if-statement


【解决方案1】:

简单的咒语

变量保存数据。函数保存代码。不要将代码放在 [string] 变量中!

source 了解更多信息/进一步:comprehensive answer on StackExchange


关于在变量中存储命令的高级口头禅是使用thecomments中指出的数组。


但是我个人不喜欢。如果我正在处理运行时信息,我只会将数组用于参数,而不是用于命令本身

我会使用函数,如下

使用函数第 1 部分

#!/usr/bin/env bash

# ...
# use descriptive function names
pingGoogleDnsOnce () {
    ping -c 1 8.8.8.8
}

if pingGoogleDnsOnce >/dev/null; then
    # do stuff
else
    # do other stuff
fi

使用函数第 2 部分

#!/usr/bin/env bash

# ...
# use descriptive function names
pingGoogleDnsOnce () {
    ping -c 1 8.8.8.8
}
# use descriptive function names
quietlyPingGoogleDnsOnce () {
    pingGoogleDnsOnce >/dev/null
}

if quietlyPingGoogleDnsOnce; then
    # do stuff
else
    # do other stuff
fi

在这两种情况下,都不需要在if-block 中明确地“检查”任何内容。 -eq 0 是不必要的

定义的函数可以像任何其他命令一样使用。主体中最后执行的命令的退出码就是函数的退出码。

所以如果ping 失败,函数pingGoogleDnsOnce 失败;如果ping成功,则函数成功

退出代码 0 表示成功

if 构造只是检查它后面的“命令”的退出代码,在我们的例子中是一个函数。


还有另一种做法,人们检查$? 的值 - 保存前一个命令的退出代码的变量。在这种情况下,构造是

if [ $? -eq 0 ]; then

但这不是推荐的。而placing the command within the if condition 是更好的方法


为什么PING=$(ping -c 8.8.8.8) 失败

$(...) 构造称为命令替换。它被()command输出替换。所以变量PING 保存ping...blah blah 的输出,输出是一个长的多行字符串,不是命令


【讨论】:

  • “不要将代码放入变量中!”。我对它来自那个博客并不感到惊讶。那句话是错误的。 Bash 是命令的操纵者,存储包含argv[0] 本身的命令参数是一种完全有效的做法。在要执行的命令是动态的情况下,这有一个有效的用例。
  • 但是你会想要使用一个数组来处理引用等。另见stackoverflow.com/questions/12136948/…
  • 我暗示使用数组。引用最初没有区别,我认识来自 #bash 的人,他们不喜欢将其存储在数组中。
  • 同时你们都没有注意到我使用了$0 我的意思是$? ? 对不起,我羞愧地扭动着
  • Do not put code in variables. 它完全可以工作直到你做一些不做的事情,虽然老专家可能会在几秒钟内发现,但世界其他地方会日复一日地调试和搜索互联网和药柜以寻求救济。建立良好的设计习惯。你会很高兴你做到了。当您必须将代码放入 vars 时,请仔细考虑并承担后果。
【解决方案2】:

您的脚本尝试将命令的输出存储到 PING 变量,而不是命令本身。有两种基本方法可以测试命令的结果,一种是检查其输出,另一种是检查其返回码。

在ping的情况下,你可以通过检查它的返回码来简单地检查它是否成功,所以你可以这样做:

if ping -qc1 8.8.8.8 -W1 >/dev/null; then

但是如果你想存储命令,你可以通过将它的参数存储为一个数组来做到这一点:

PING=(ping -qc1 8.8.8.8 -W1)

if "${PING[@]}"; then

但是,这不允许您像 >/dev/null 这样存储重定向,因此与其将其存储为数组,不如将其存储为函数:

do_ping() {
    ping -qc1 8.8.8.8 -W1 >/dev/null
}

然后就可以执行了:

if do_ping; then

注意使用与其外部命令名称相似的函数名称,因为这会导致循环调用:

ping() {
    ping -qc1 8.8.8.8 -W1 >/dev/null
}

您可以使用command 命令来避免它:

ping() {
    command ping -qc1 8.8.8.8 -W1 >/dev/null
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    • 2010-10-22
    • 2016-04-23
    • 1970-01-01
    • 2021-11-18
    相关资源
    最近更新 更多