(冒号)GNUBash内置的目的是什么?
一个命令什么也不做,只是一个注释引导者,但实际上是一个内置的shell,它的目的是什么 它比每次调用将注释插入脚本的速度慢约40%,这可能因注释的大小而异。我能看到的唯一可能的原因是:(冒号)GNUBash内置的目的是什么?,bash,shell,built-in,Bash,Shell,Built In,一个命令什么也不做,只是一个注释引导者,但实际上是一个内置的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 i
# 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' (lazy programming)
while : ; do command ; done
#穷人的延迟功能
对于((x=0;x历史上的,Bourne shells没有true
和false
作为内置命令。true
被简单地别名为:
,而false
类似于let 0
>代码> <>代码> Trime。对于一个简单的例子,考虑到既没有<代码> < /> >流水线运算符,也没有<代码> > <代码>列表操作符(如一些古贝壳的情况)。这使得
if
语句的else
子句成为基于退出状态进行分支的唯一方法:
if command; then :; else ...; fi
由于如果需要一个非空,那么子句和注释不算为非空,:
用作禁止操作
如今(即:在现代语境中)通常可以使用:
或true
。两者都是由POSIX指定的,有些人认为true
更容易阅读。但是有一个有趣的区别::
是所谓的POSIX特殊内置,而true
是常规内置
- 需要在shell中内置特殊的内置程序;常规的内置程序只是“典型”的内置程序,但没有严格的保证。在大多数系统的路径中,通常不应该有一个名为
:
且具有true
功能的常规程序
- 可能最关键的区别在于,对于特殊的内置,内置设置的任何变量(即使在简单命令求值期间的环境中)在命令完成后仍然存在,如使用ksh93所示:
$ unset x; ( x=hi :; echo "$x" )
hi
$ ( x=hi true; echo "$x" )
$
请注意,Zsh忽略了这一要求,GNUBASH也忽略了这一要求,但在POSIX兼容模式下运行时除外,但所有其他主要的“POSIX sh派生”shell都遵守这一要求,包括dash、ksh93和mksh
- 另一个区别是,常规内置必须与
exec
兼容-这里使用Bash演示:
$ ( exec : )
-bash: exec: :: not found
$ ( exec true )
$
- POSIX还明确指出,
:
可能比true
更快,当然这是一个特定于实现的细节
您可以将其与反勾号(`
)结合使用来执行命令,而不显示其输出,如下所示:
: `some_command`
45 10 * * * : Backup for database ; /opt/backup.sh
#!/usr/bin/env sh
':' //; exec "$(command -v node)" "$0" "$@"
':'
~function(){ ... }
当然,您可以只执行一些命令>/dev/null
,但是:
-版本稍微短一些
尽管如此,我不建议实际这样做,因为这只会让人感到困惑。它只是作为一个可能的用例出现在我的脑海中。它类似于Python中的pass
一种用途是在函数被写入之前将其存根:
future_function () { :; }
我使用它来轻松启用/禁用变量命令:
#!/bin/bash
if [[ "$VERBOSE" == "" || "$VERBOSE" == "0" ]]; then
vecho=":" # no "verbose echo"
else
vecho=echo # enable "verbose echo"
fi
$vecho "Verbose echo is ON"
因此
这使得脚本干净。这不能用“#”完成
而且
是保证“afile”存在但长度为0的最简单方法之一。对于:
来说,一个有用的应用程序是,如果您只对参数扩展的副作用感兴趣,而不是实际将其结果传递给命令
在这种情况下,您可以使用参数展开作为:
或false
的参数,具体取决于您想要的退出状态是0还是1
: "${var:=$1}"
由于:
是一个内置的,它应该非常快。如果您想将文件截断为零字节,这对清除日志非常有用,请尝试以下操作:
:> file.log
:
也可以用于块注释(类似于C语言中的/**/)。例如,如果要跳过脚本中的一块代码,可以执行以下操作:
: << 'SKIP'
your code block here
SKIP
:其他答案中未提及的另外两个用途:
登录中
以这个脚本为例:
set -x
: Logging message here
example_command
第一行,set-x
,使shell在运行命令之前打印出命令。这是一个非常有用的构造。缺点是,通常的echo Log message
类型的语句现在会打印两次消息。冒号方法解决了这一问题。请注意,您仍然需要像对或echo
Cron职务
我看到它被用于cron作业,如下所示:
: `some_command`
45 10 * * * : Backup for database ; /opt/backup.sh
#!/usr/bin/env sh
':' //; exec "$(command -v node)" "$0" "$@"
':'
~function(){ ... }
这是一个cron作业,每天10:45运行脚本/opt/backup.sh
。这种技术的优点是,当/opt/backup.sh
打印一些输出时,它可以使电子邮件主题看起来更好看。它也适用于多语言程序:
#!/usr/bin/env sh
':' //; exec "$(command -v node)" "$0" "$@"
~function(){ ... }
这现在既是一个可执行的shell脚本,也是一个JavaScript程序:这意味着/filename.js
,sh filename.js
,和节点filename.js
都可以工作
(肯定有点奇怪,但仍然有效。)
应要求进行一些解释:
- Shell脚本逐行计算;
exec
命令在运行时终止Shell并用结果命令替换其进程。这意味着对于Shell,程序如下所示:
: `some_command`
45 10 * * * : Backup for database ; /opt/backup.sh
#!/usr/bin/env sh
':' //; exec "$(command -v node)" "$0" "$@"
':'
~function(){ ... }
- 只要单词中没有出现参数扩展或别名,shell脚本中的任何单词都可以用引号括起来,而不改变其“含义”;这意味着
:”
等同于:
(我们在这里只用引号括起来,以实现下面描述的JavaScript语义)
- …如上所述,第一行的第一个命令是no op(它转换为
://
,或者如果您喜欢引用