一个什么都不做的命令,只不过是一个注释引导,但实际上是一个内置的shell,它的目的是什么?

它比每次调用在脚本中插入注释要慢40%左右,这可能取决于注释的大小。我认为唯一可能的原因是:

# poor man's delay function
for ((x=0;x<100000;++x)) ; do : ; done

# inserting comments into string of commands
command ; command ; : we need a comment in here for some reason ; command

# an alias for `true'
while : ; do command ; done

我想我真正想要的是它在历史上的应用。


当前回答

它类似于Python中的传递。

一种用法是将一个函数存根,直到它被写入:

future_function () { :; }

其他回答

它类似于Python中的传递。

一种用法是将一个函数存根,直到它被写入:

future_function () { :; }

:的一个有用的应用程序是,如果您只对使用参数展开的副作用感兴趣,而不是实际将其结果传递给命令。

在这种情况下,您使用参数展开作为参数:或false,这取决于您想要的退出状态是0还是1。一个例子是

: "${var:=$1}"

由于:是内置的,它应该相当快。

它对多语言程序也很有用:

#!/usr/bin/env sh
':' //; exec "$(command -v node)" "$0" "$@"
~function(){ ... }

现在这既是一个可执行的shell脚本,也是一个JavaScript程序:这意味着。/filename.js、sh filename.js和node filename.js都可以工作。

(这种用法确实有点奇怪,但还是很有效。)


请作一些说明:

Shell-scripts are evaluated line-by-line; and the exec command, when run, terminates the shell and replaces it's process with the resultant command. This means that to the shell, the program looks like this: #!/usr/bin/env sh ':' //; exec "$(command -v node)" "$0" "$@" As long as no parameter expansion or aliasing is occurring in the word, any word in a shell-script can be wrapped in quotes without changing its' meaning; this means that ':' is equivalent to : (we've only wrapped it in quotes here to achieve the JavaScript semantics described below) ... and as described above, the first command on the first line is a no-op (it translates to : //, or if you prefer to quote the words, ':' '//'. Notice that the // carries no special meaning here, as it does in JavaScript; it's just a meaningless word that's being thrown away.) Finally, the second command on the first line (after the semicolon), is the real meat of the program: it's the exec call which replaces the shell-script being invoked, with a Node.js process invoked to evaluate the rest of the script. Meanwhile, the first line, in JavaScript, parses as a string-literal (':'), and then a comment, which is deleted; thus, to JavaScript, the program looks like this: ':' ~function(){ ... } Since the string-literal is on a line by itself, it is a no-op statement, and is thus stripped from the program; that means that the entire line is removed, leaving only your program-code (in this example, the function(){ ... } body.)

自我记录的功能

您还可以使用:将文档嵌入到函数中。

假设您有一个库脚本mylib.sh,它提供了各种函数。您可以将库(。Mylib.sh),然后直接调用函数(lib_function1 arg1 arg2),或者避免使您的命名空间混乱,并使用函数参数调用库(Mylib.sh lib_function1 arg1 arg2)。

如果您还可以输入mylib.sh——help并获得可用函数及其用法的列表,而不必在帮助文本中手动维护函数列表,这不是很好吗?

#!/bin/bash

# all "public" functions must start with this prefix
LIB_PREFIX='lib_'

# "public" library functions
lib_function1() {
    : This function does something complicated with two arguments.
    :
    : Parameters:
    : '   arg1 - first argument ($1)'
    : '   arg2 - second argument'
    :
    : Result:
    : "   it's complicated"

    # actual function code starts here
}

lib_function2() {
    : Function documentation

    # function code here
}

# help function
--help() {
    echo MyLib v0.0.1
    echo
    echo Usage: mylib.sh [function_name [args]]
    echo
    echo Available functions:
    declare -f | sed -n -e '/^'$LIB_PREFIX'/,/^}$/{/\(^'$LIB_PREFIX'\)\|\(^[ \t]*:\)/{
        s/^\('$LIB_PREFIX'.*\) ()/\n=== \1 ===/;s/^[ \t]*: \?['\''"]\?/    /;s/['\''"]\?;\?$//;p}}'
}

# main code
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
    # the script was executed instead of sourced
    # invoke requested function or display help
    if [ "$(type -t - "$1" 2>/dev/null)" = function ]; then
        "$@"
    else
        --help
    fi
fi

关于代码的一些注释:

All "public" functions have the same prefix. Only these are meant to be invoked by the user, and to be listed in the help text. The self-documenting feature relies on the previous point, and uses declare -f to enumerate all available functions, then filters them through sed to only display functions with the appropriate prefix. It is a good idea to enclose the documentation in single quotes, to prevent undesired expansion and whitespace removal. You'll also need to be careful when using apostrophes/quotes in the text. You could write code to internalize the library prefix, i.e. the user only has to type mylib.sh function1 and it gets translated internally to lib_function1. This is an exercise left to the reader. The help function is named "--help". This is a convenient (i.e. lazy) approach that uses the library invoke mechanism to display the help itself, without having to code an extra check for $1. At the same time, it will clutter your namespace if you source the library. If you don't like that, you can either change the name to something like lib_help or actually check the args for --help in the main code and invoke the help function manually.

:也可以是块注释(类似于C语言中的/* */)。例如,如果你想在脚本中跳过一段代码,你可以这样做:

: << 'SKIP'

your code block here

SKIP