155

bash(:)でnoopを検索しましたが、適切な情報が見つかりませんでした。この演算子の正確な目的または使用例は何ですか?

私はフォローしてみました、そしてそれは私にとってこのように働いています:

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

この演算子のリアルタイムの使用例、または使用が義務付けられている場所を教えてください。

4

12 に答える 12

219

それは歴史的な理由でもっとあります。組み込みのコロン:は、とまったく同じtrueです。true戻り値が重要な場合、たとえば無限ループで使用するのが伝統的です。

while true; do
  echo 'Going on forever'
done

:シェル構文にコマンドが必要であるが、何もする必要がない場合に使用するのが伝統的です。

while keep_waiting; do
  : # busy-wait
done

ビルトインはThompsonシェル:にまでさかのぼり、Unixv6に存在していました。Thompsonシェルのステートメントのラベルインジケーターでした。ラベルは任意のテキストにすることができるため、コメントインジケーターとしても使用できます(がない場合は、事実上コメントになります)。Bourneシェルにはありませんでしたが、保持されていました。:goto:goto comment: commentgoto:

を使用する一般的なイディオムはです。これ:は、設定されていない場合はに設定され、すでに設定されている場合は何もしません。この構成は変数置換の形式でのみ存在し、この変数置換は何らかの形でコマンドの一部である必要があります。no-opコマンドは適切に機能します。: ${var=VALUE}varVALUEvar

コロンビルトインはどのような目的に役立ちますか?も参照してください。。

于 2012-09-13T11:51:13.273 に答える
33

すべてのコードをコメントアウトするときに、ifステートメントに使用します。たとえば、次のようなテストがあります。

if [ "$foo" != "1" ]
then
    echo Success
fi

ただし、以下に含まれるすべてのものを一時的にコメントアウトする必要があります。

if [ "$foo" != "1" ]
then
    #echo Success
fi

これにより、bashで構文エラーが発生します。

line 4: syntax error near unexpected token `fi'
line 4: `fi'

Bashは空のブロック(WTF)を持つことはできません。したがって、no-opを追加します。

if [ "$foo" != "1" ]
then
    #echo Success
    :
fi

または、no-opを使用して行をコメントアウトできます。

if [ "$foo" != "1" ]
then
    : echo Success
fi
于 2017-02-15T11:09:40.900 に答える
15

を使用するset- e場合は、障害が発生した場合にスクリプトを終了しない|| :ための優れた方法です(明示的にパスします)。

于 2016-07-12T15:04:31.633 に答える
7

:成功するが何もしないコマンドを提供するために使用します。この例では、「verbosity」コマンドは、に設定することにより、デフォルトでオフになっています:。'v'オプションはそれをオンにします。

#!/bin/sh
# example
verbosity=:                         
while getopts v OPT ; do          
   case $OPT in                  
       v)        
           verbosity=/bin/realpath 
       ;;
       *)
           exit "Cancelled"
       ;;             
   esac                          
done                              

# `$verbosity` always succeeds by default, but does nothing.                              
for i in * ; do                   
  echo $i $($verbosity $i)         
done                              

$ example
   file

$ example -v
   file /home/me/file  
于 2016-05-11T18:33:57.943 に答える
6

alias引数を無視する

引数を取らないエイリアスが必要な場合があります。あなたはそれを使用してそれを行うことができます:

> alias alert_with_args='echo hello there'

> alias alert='echo hello there;:'

> alert_with_args blabla
hello there blabla

> alert blabla
hello there
于 2017-07-05T21:26:53.437 に答える
6

1つの用途は、複数行コメントとして、またはヒアファイルと組み合わせて使用​​することにより、テスト目的でコードの一部をコメントアウトすることです。

: << 'EOF'

This part of the script is a commented out

EOF

EOFのように、内部のコードが評価されないように、引用符を使用することを忘れないでください$(foo)。また、、、、などの直感的なターミネータ名を使用する価値があるかもしれませNOTESん。SCRATCHPADTODO

于 2017-11-11T16:58:18.403 に答える
3

私の2つ。

PODコメントを埋め込む

の非常にファンキーなアプリケーション:は、PODコメントをbashスクリプトに埋め込んで、マニュアルページをすばやく生成できるようにするためのものです。もちろん、最終的にはスクリプト全体をPerlで書き直すことになります;-)

実行時関数バインディング

これは、実行時に関数をバインドするための一種のコードパターンです。Fi、特定のフラグが設定されている場合にのみ何かを実行するデバッグ機能があります。

#!/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'

あなたが得る:

$ ./noop-demo.sh 
Testing noop alias...
$ DBG=1 ./noop-demo.sh 
Testing noop alias...
[DBG] foo bar
于 2016-10-28T19:50:32.157 に答える
2

no-op句を使用すると、コードが読みやすくなる場合があります。

それは意見の問題かもしれませんが、ここに例があります。2つのUNIXパスを使用して機能する関数を作成したとします。あるパスから別のパスにcdするために必要な「パスの変更」を計算します。パスは両方とも「/」で始まる必要がある、または両方がそうではないという制限を関数に設定します。

function chgpath() {
    # toC, fromC are the first characters of the argument paths.
    if [[ "$toC" == / && "$fromC" == / ]] || [[ "$toC" != / && "$fromC" != / ]]
    then
        true      # continue with function
    else
        return 1  # Skip function.
    fi

一部の開発者はno-opを削除したいと思うでしょうが、それは条件付きを否定することを意味します:

function chgpath() {
    # toC, fromC are the first characters of the argument paths.
    if [[ "$toC" != / || "$fromC" == / ]] && [[ "$toC" == / || "$fromC" != / ]]
    then
        return 1  # Skip function.
    fi

さて、私の意見では、if節からは、関数の実行をスキップしたい条件はそれほど明確ではありません。no-opを排除して明確に行うには、if句を関数の外に移動します。

    if [[ "$toC" == / && "$fromC" == / ]] || [[ "$toC" != / && "$fromC" != / ]]
    then
        cdPath=$(chgPath pathA pathB)   # (we moved the conditional outside)

見た目は良くなりますが、多くの場合、これを行うことはできません。関数内でチェックを実行する必要があります。

では、これはどのくらいの頻度で発生しますか?あまり頻繁ではありません。たぶん年に1、2回。それは十分に頻繁に起こるので、あなたはそれを知っているべきです。(言語に関係なく)コードの可読性が向上すると思うときは、それを使用することを躊躇しません。

于 2014-11-05T14:18:52.450 に答える
2

この答えにいくらか関連して、私はこのノーオペレーションがポリグロットスクリプトをハックするのにかなり便利だと思います。たとえば、bashとvimscriptの両方に有効なコメントは次のとおりです。

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

trueもちろん、同じように使用した可能性もあります:が、句読点であり、無関係な英語の単語ではないことから、構文トークンであることが明確になります。


なぜ誰かがポリグロットスクリプトを書くようなトリッキーなことをするのでしょうか(それはクールであることに加えて):ファイルがファイルXを参照する、通常いくつかの異なる言語でいくつかのスクリプトファイルを書く状況で役立ちますY

Xこのような状況では、両方のスクリプトを1つのpolyglotファイルに結合することで、へのパスを決定するための作業を回避できますY(これは単純です"$0")。さらに重要なことは、プログラムの移動や配布がより便利になることです。

  • 一般的な例。シバンにはよく知られた長年の問題があります。ほとんどのシステム(LinuxやCygwinを含む)では、1つの引数のみをインタープリターに渡すことができます。次のシバン:

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

    次のコマンドを実行します。

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

    意図されたものではありません:

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

    したがって、次のようなラッパースクリプトを作成することになります。

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

    ここでポリグロシアが登場します。

  • より具体的な例。私はかつて、Vimを呼び出すbashスクリプトを作成しました。私はVimに追加のセットアップを与える必要がありました。これはオプションで行うことができます--cmd "arbitrary vimscript command here"。ただし、その設定はかなりのものだったので、文字列にインライン化するのはひどいものでした(可能であれば)。したがって、より良い解決策は、それをいくつかの構成ファイルのextenso-S "/path/to/file"に書き込んでから、Vimにそのファイルを.で読み取らせることでした。したがって、私はポリグロットbash/vimscriptファイルになりました。

于 2018-08-06T16:05:03.230 に答える
2

別のコマンドの成功にチェーンしたいコマンドがあるとします。

cmd="some command..."
$cmd
[ $? -eq 0 ] && some-other-command

しかし、今度は条件付きでコマンドを実行し、実行されるコマンド(ドライラン)を表示したいとします。

cmd="some command..."
[ ! -z "$DEBUG" ] && echo $cmd
[ -z "$NOEXEC" ] && $cmd
[ $? -eq 0 ] && {
    cmd="some-other-command"
    [ ! -z "$DEBUG" ] && echo $cmd
    [ -z "$NOEXEC" ] && $cmd
}

したがって、DEBUGとNOEXECを設定した場合、2番目のコマンドは表示されません。これは、最初のコマンドが実行されないためです(NOEXECが空ではないため)が、その事実を評価すると1が返されます。これは、従属コマンドが実行されないことを意味します(ただし、ドライランであるため実行する必要があります)。したがって、これを修正するには、スタックに残っている終了値をnoopでリセットできます。

[ -z "$NOEXEC" ] && $cmd || :
于 2019-06-21T23:11:58.860 に答える
1

また、デフォルトの変数を定義するためにスクリプトを使用しました。


: ${VARIABLE1:=my_default_value}
: ${VARIABLE2:=other_default_value}
call-my-script ${VARIABLE1} ${VARIABLE2}

于 2020-07-01T00:05:41.573 に答える
0

次のように、DockerファイルでRUNコマンドを調整するために使用することがあります。

RUN : \
    && somecommand1 \
    && somecommand2 \
    && somecommand3

私にとって、それはよりよく読みます:

RUN somecommand1 \
    && somecommand2 \
    && somecommand3

もちろん、これは好みの問題です

于 2020-09-18T09:25:32.990 に答える