web-dev-qa-db-ja.com

コロンのビルトインはどのような目的に役立ちますか?

私は多くのシェルスクリプトをハッキングしてきましたが、最も単純なものが私を困惑させることがあります。今日、:(コロン)bashビルトインを広範囲に使用するスクリプトに遭遇しました。

documenation は非常に単純なようです:

: (a colon)  
     : [arguments]  

引数を拡張してリダイレクトを実行する以外に何もしません。戻り状況はゼロです。

ただし、以前はこれがシェル拡張のデモンストレーションで使用されるのを見ただけです。私が遭遇したスクリプトの使用例は、この構造を広範囲に使用しました。

if [ -f ${file} ]; then
    grep some_string ${file} >> otherfile || :
    grep other_string ${file} >> otherfile || :
fi

実際には何百ものgrepがありましたが、それらは同じです。上記の単純な構造以外に、入出力リダイレクトはありません。スクリプトの戻り値はチェックされません。

私はこれを、「または何もしない」と言う役に立たない構造として読んでいます。これらのグループを「または何もしない」で終わらせることができる目的は何ですか?どのような場合に、このコンストラクトは、単にすべてのインスタンスから|| :を除外するのとは異なる結果を引き起こしますか?

45
Caleb

スクリプトの_:_ sがtrueの代わりに使用されているようです。 grepがファイル内で一致するものを見つけられない場合、ゼロ以外の終了コードを返します。 jw013がコメントで言及しているように、errexitが設定されている場合、おそらくShebang行の_-e_によって、grepsのいずれかが一致を検出できない場合、スクリプトは終了します。明らかに、それは著者が望んでいたものではないので、(s)彼は_|| :_を追加して、より一般的な(私の経験では)_|| true_/_|| /bin/true_。

30
Kevin

:ビルトインは、Bashの「デフォルト値の割り当て」シェル拡張でも役立ちます。この拡張は、副作用のためにのみ使用されることが多く、拡張された値は破棄されます。

# assign FOO=bar iff FOO is unset
: ${FOO:=bar}
38
Joni

過去に:を使用した場所は2つ考えられます。

while :
do
     Shell commands
     some exit condition
done

それは永久ループです。

function doSomethingStub {
    :
}

最上位の制御フローを正しくするために、スタブ関数を挿入します。

私が昔に見た用途の1つ:#!/bin/sh(またはその他の)行の代わりに、:行が表示されます。古いReal UnixカーネルまたはReal Unixシェルの一部では、「私はシェルスクリプトです。shで実行してください」という意味で使用されています。私が覚えているように、これはcshが一般的なインタラクティブシェルとして普及したときのことです。

22
Bruce Ediger

組み込みの:は、すでに Thompson Shell に含まれていました— 1975年には documented for nix V6 です。ThompsonShellでは、 :goto コマンドのラベルを示しています。 で始まる行でgotoを呼び出そうとしなかった場合、その行は事実上コメントでした。

Bourne Shell 、私たちが知っているBourne/POSIXシェルの祖先であり、私が知っているgotoがなかったが、:をno-opコマンドとして保持した(それはすでに nix V7 に存在していました)。

私は古いリファレンスを探し出しました:KernighanとPikeによる "UNIXプログラミング環境"(c)1984。

ページ147(シェルプログラミング)は次のように述べています。

「:」は、シェルの組み込みコマンドで、引数を評価して「true」を返すだけです。代わりに[スクリプトの例を参照]としてtrueを使用することもできますが、これは単にtrueの終了ステータスを返すだけです。 (falseコマンドもあります。)しかし、ファイルシステムからコマンドを実行しないため、「:」はtrueよりも効率的です。 [斜体/強調は私のものです。]

14
fracjackmac

":"はデバッグに便利です。

DEBUGLOG=": debugfunction"

statement
statement
$DEBUGLOG arg1 arg2 ...
statement
statement

通常、デバッグ機能は実行されないため、shはnoopをステップオーバーするだけです(変数とワイルドカードは展開されます)。さらに詳細なデバッグが必要な場合は、変数からnoopを削除し、必要な引数を使用してdebugfunctionを呼び出します。

もう1つの便利な使用法は、ブロック構文としての使用です。これは、シェル構文に欠けている機能です。

: << COMMENT
all --statements --in --here
are now -a here document which are
passed to --the noop
COMMENT
9
Colin

シェルの初期のバージョンにはコメント構文がないことを思い出したようです。 :で始まる行(おそらく実際の実行可能ファイルであり、/bin/trueに似ています)が最良の代替案です。

ここに man page があります Thompson Shell (関係なし);コメント構文についての言及はありません。

9
Keith Thompson