*nix 中尾随的“:”(冒号)是什么意思?

*nix 中尾随的“:”(冒号)是什么意思?

我目前正在关注有关 shell 脚本编写的教程,该教程位于此处: http://www.cs.columbia.edu/~sauce/tutorial/ashell.html我相信我的剧本完全符合这个剧本。但是,当我尝试运行该示例时,我的输出不匹配。由于我不想含糊其辞,只是问“为什么它不起作用?”,所以我将重点关注我不明白的部分:为什么命令":"后面有一个testlogin:?我读过许多论坛,讨论了" : "(两边都有空格)和前导的含义":",但没有提到滞后冒号的使用。在这种情况下是什么意思?如果这是一个拼写错误,任何人都可以帮我找到示例中可能导致其无法正常运行的另一个拼写错误吗?

任何帮助将不胜感激!

代码(完全从我上面链接的网站复制)如下:

#testlogin
useron(){
if ( who | grep $1 > /dev/null)
then echo $1 is logged in
else echo $1 is not logged in
fi 
}
if test $# != 1
then echo testlogin: username
else useron
fi

和输出

paul@paul-LC22UP:~$ .testlogin paul
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
is no logged in

答案1

testlogin这里不是命令,而是 的参数echo。完整的命令是:

 echo testlogin: username

echo只是吐出您提供给 STDOUT 的文本。所以冒号没有特殊含义,它是 逐字输出的一部分echo。如果您使用错误数量的参数调用脚本,则输出如下:

$ ./testlogin
testlogin: username
$ ./testlogin fred bill adam
testlogin: username

这是一个奇怪的输出,但不一定是拼写错误。我通常会期待更多类似的事情:

$ ./testlogin
Usage: testlogin username

整个脚本不起作用的原因是作者在调用该useron函数时犯了一个微妙的错误,并且可能在发布脚本之前没有测试他们的脚本(或者他们会注意到您所做的相同错误)。函数$1useron是第一个参数到那个函数,而不是整个脚本;但由于useron没有使用任何参数调用,所以它是空字符串,因此它最终运行命令:

$ who | grep

这将给出greps 的使用信息,然后始终触发else条件的分支。您可以通过将第一个参数传递给脚本来解决此问题,useron如下所示:

else useron $1

答案2

您链接到的网站质量非常低shell scripts
为了预先回答您的问题,“尾随冒号”对 shell 没有特殊含义,它只是要打印在屏幕上的字符串的一部分。

然而页面上的代码有这个缺陷:

  • 你应该学习的最重要的问题是“引用你的扩展”。
    那就是“参数扩展”(变量),但也有其他扩展。
    这是我写这篇文章的主要原因。养成不引用扩展的习惯是非常糟糕的。

  • 没有提到舍邦机制页面中的任何位置。 (这意味着第一行像 #!/bin/bash 或类似的)。编写脚本而不说明运行脚本的 shell 类型肯定是错误和问题的根源。

  • 第 11 行缺少用于调用该函数的参数。它应该是这样的:else useron "$1"而不是else useron

在这三个明显的错误之后,我们可以运行脚本:

$ testlogin
testlogin: username

如您所见,第 10 行的字符串按原样打印在控制台上。
结尾的冒号:对 shell 来说没有任何意义,当字符串被引用为这样时,这一点就变得很清楚:

then echo "testlogin: username"

事实上,IMO,这会更明确:

then echo "A parameter is needed, type something like 'testlogin: username'"

现在,不带参数执行脚本会打印出有用的答案。
写一个用户名也可以:

$ testlogin joe
joe is not logged in

进行上述更改的脚本是:

#/bin/sh
useron(){
    if    ( who | grep "$1" > /dev/null)
    then  echo "$1 is logged in"
    else  echo "$1 is not logged in"
    fi
}

if    test "$#" != "1"
then  echo "Parameter missing, type something like 'testlogin: username'"
else  useron "$1"
fi

现在,第二轮问题:

  • 外部test命令在大多数 shell 上已不再使用。
    它已被完全等效的外壳[[[更现代的外壳所取代。脚本中使用的行:if test "$#" != "1"应替换为:

    if    [ "$#" != "1" ]
    
  • 现在我们来谈谈写作风格。在现代,更常见的是这样写的脚本(但这是个人喜好的问题):

#/bin/sh
useron(){
    if ( who | grep "$1" > /dev/null); then
        echo "$1 is logged in"
    else
        echo "$1 is not logged in"
    fi
}

if  [ "$#" != "1" ]; then
    echo "Parameter missing, type something like 'testlogin: username'"
else
    useron "$1"
fi

相关内容