What is the use case of noop [:] in bash?

2019-01-21 02:09发布

I searched for noop in bash (:), but was not able to find any good information. What is the exact purpose or use case of this operator?

I tried following and it's working like this for me:

[mandy@root]$ a=11
[mandy@root]$ b=20
[mandy@root]$ c=30
[mandy@root]$ echo $a; : echo $b ; echo $c
10
30

Please let me know, any use case of this operator in real time or any place where it is mandatory to use it.

标签: bash shell noop
9条回答
戒情不戒烟
2楼-- · 2019-01-21 03:03

Two of mine.

Embed POD comments

A quite funky application of : is for embedding POD comments in bash scripts, so that man pages can be quickly generated. Of course, one would eventually rewrite the whole script in Perl ;-)

Run-time function binding

This is a sort of code pattern for binding functions at run-time. F.i., have a debugging function to do something only if a certain flag is set:

#!/bin/bash
# noop-demo.sh 
shopt -s expand_aliases

dbg=${DBG:-''}

function _log_dbg {
    echo >&2 "[DBG] $@"
}

log_dbg_hook=':'

[ "$dbg" ] && log_dbg_hook='_log_dbg'

alias log_dbg=$log_dbg_hook


echo "Testing noop alias..."
log_dbg 'foo' 'bar'

You get:

$ ./noop-demo.sh 
Testing noop alias...
$ DBG=1 ./noop-demo.sh 
Testing noop alias...
[DBG] foo bar
查看更多
▲ chillily
3楼-- · 2019-01-21 03:06

Somewhat related to this answer, I find this no-op rather convenient to hack polyglot scripts. For example, here is a valid comment both for bash and for vimscript:

":" #    this is a comment
":" #    in bash, ‘:’ is a no-op and ‘#’ starts a comment line
":" #    in vimscript, ‘"’ starts a comment line

Sure, we may have used true just as well, but : being a punctuation sign and not an irrelevant English word makes it clear that it is a syntax token.


As for why would someone do such a tricky thing as writing a polyglot script (besides it being cool): it proves helpful in situations where we would normally write several script files in several different languages, with file X referring to file Y.

In such a situation, combining both scripts in a single, polyglot file avoids any work in X for determining the path to Y (it is simply "$0"). More importantly, it makes it more convenient to move around or distribute the program.

  • A common example. There is a well-known, long-standing issue with shebangs: most systems (including Linux and Cygwin) allow only one argument to be passed to the interpreter. The following shebang:

    #!/usr/bin/env interpreter --load-libA --load-libB
    

    will fire the following command:

    /usr/bin/env "interpreter --load-libA --load-libB" "/path/to/script"
    

    and not the intended:

    /usr/bin/env interpreter --load-libA --load-libB "/path/to/script"
    

    Thus, you would end up writing a wrapper script, such as:

    #!/usr/bin/env sh
    /usr/bin/env interpreter --load-libA --load-libB "/path/to/script"
    

    This is where polyglossia enters the stage.

  • A more specific example. I once wrote a bash script which, among other things, invoked Vim. I needed to give Vim additional setup, which could be done with the option --cmd "arbitrary vimscript command here". However, that setup was substantial, so that inlining it in a string would have been terrible (if ever possible). Hence, a better solution was to write it in extenso in some configuration file, then make Vim read that file with -S "/path/to/file". Hence I ended up with a polyglot bash/vimscript file.

查看更多
小情绪 Triste *
4楼-- · 2019-01-21 03:14

It's there more for historical reasons. The colon builtin : is exactly equivalent to true. It's traditional to use true when the return value is important, for example in an infinite loop:

while true; do
  echo 'Going on forever'
done

It's traditional to use : when the shell syntax requires a command but you have nothing to do.

while keep_waiting; do
  : # busy-wait
done

The : builtin dates all the way back to the Thompson shell, it was present in Unix v6. : was a label indicator for the Thompson shell's goto statement. The label could be any text, so : doubled up as a comment indicator (if there is no goto comment, then : comment is effectively a comment). The Bourne shell didn't have goto but kept :.

A common idiom that uses : is : ${var=VALUE}, which sets var to VALUE if it was unset and does nothing if var was already set. This construct only exists in the form of a variable substitution, and this variable substitution needs to be part of a command somehow: a no-op command serves nicely.

See also What purpose does the colon builtin serve?.

查看更多
登录 后发表回答