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


45

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

documenationは、単純な十分です。

: (a colon)  
     : [arguments]  

引数を展開してリダイレクトを実行する以外は何もしません。戻りステータスはゼロです。

ただし、これはシェル拡張のデモンストレーションで使用されているだけです。私が出会ったスクリプトのユースケースでは、この構造を広範囲に使用しました。

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

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

私はこれを「または何もしない」という意味のない構成として読んでいます。これらの不満を「または何もしない」で終わる目的は何ですか?どのような場合、この構成は|| :、すべてのインスタンスから単純に離脱するのとは異なる結果を引き起こしますか?


10
私が見ることができる1つの可能な目的は:、の代替として使用することtrueです。おそらくerrexit設定されており、作成者はいくつかのコマンドの終了ステータスを気にしません。
jw013

9
へー、SO
jw013の

StackoverflowのリンクされたページはIMOの方が少し包括的です(このページとリンクされたページの両方を読むのが良いです)。
トレバーボイドスミス

回答:


29

表示された:スクリプト内のsがの代わりに使用されていますtruegrepファイル内で一致するものが見つからない場合、ゼロ以外の終了コードを返します。jw013がコメントで言及しているように、errexit設定されている場合、おそらく-eシェバン行で、grepsのいずれかが一致を見つけられなかった場合、スクリプトは終了します。明らかに、それは著者が望んでいたものではない|| :ため、(私の経験では)|| true/のように、特定の複合コマンドの終了ステータスを常にゼロにするように追加しました|| /bin/true


ああ。これはRPMビルドスクリプトの概念であり、スクリプト内で終了コードのチェックは行われませんでしたが、親プロセスが監視している可能性があることを忘れていました。
カレブ

8
その場合、私はそれを貧弱なスクリプトの練習と呼びます。機能的にはtrue代わりにを使用するのと同等ですが、セマンティックの意図はを使用するとはるかに明確になりtrueます。 :明示的なNOPが必要な場合により適しています。
jw013

私の経験では、これはRPMスクリプトの一般的な方法です。おそらくないはずですが、そこにあります。
mattdm

一部の純粋主義者は、:代わりにビルトインであり、通常はオーバーヘッドが多いコンパイル済みバイナリであるtrueため:、好む人もいます。通常、コードが読みやすいために使用します(同様に、の代わりに使用することを好みます)。bashtruetruesource.
トレバーボイドスミス

36

:組み込みも拡大がしばしば副作用のためだけに使用され、展開された値が捨てられるバッシュ「アサインデフォルト値」シェル拡張、と便利です。

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

2
これを探してここに来ましたが、デフォルト値を宣言するスクリプトでこのパターンを見たときに困惑しました。
駆け引き

21

:過去に使用した2つの場所を考えることができます。

while :
do
     shell commands
     some exit condition
done

それは永遠のループです。

function doSomethingStub {
    :
}

トップレベルの制御フローを正しく取得するために、スタブ関数を挿入します。

昔に私が見た1つの使用法:(#!/bin/shまたは何でも)行の代わりに、行が表示されます:。古いReal UnixカーネルまたはReal Unixシェルの一部は、それを使用して「私はシェルスクリプトです。shを実行しました」と意味します。私が思い出したように、これはcshが一般的な対話型シェルとして普及していたときのことでした。


@BruceEdiger:「シェコロン」の行への参照はありますか?
l0b0

7
最後に見つかった「:スクリプトの冒頭で、」基準と解説:faqs.org/faqs/unix-faq/faq/part3/section-16.html
ブルースEdiger

1
開始時の動作:は非常に奇妙です。私はそれが実際にスクリプトを実行する原因になることがわかりましたsh。ここで、シバンなしでスクリプトを開始するときは...実行中のシェルでスクリプトを実行しようとします(bash実行しているbash場合は、実行しているかのようcshに実行しようとしますcsh
トレバーボイドスミス

19

:ビルトインはすでにだったトンプソンシェルそれはだ- 文書化のためのUnix V6、トンプソンシェルでは1975年に:のラベル示さgotoコマンドを。でgoto始まる行を呼び出そうとしたことがない場合、その行は事実上コメントでした。

Bourneシェル、我々は彼らを知っているように、ボーン/ POSIXシェルの祖先は、持っていなかったgoto私が知っているが、保持していること:(それがすでに存在していたノーオペレーションコマンドとしてのUnix V7)。


有益な歴史的背景のポイント。
トニー・バルガンスキー

12

古いリファレンスを掘り出しました。「UNIXプログラミング環境」(c)1984年、KernighanとPike。

147ページ(シェルプログラミング)のコメント:

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


2
もちろん、true多くのシステムではシェルもビルトインされています。
トリプリー

8

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

これは、古代のトンプソンシェル(関係なし)のマニュアルページです。コメント構文についての言及はありません。


4
の起源:は、実際にはgotoコマンドのラベルインジケーターであり、古代のシェル(どれがわからない)でした。: something一致するがない場合、ラベルは実際にコメントとして使用できgotoます。練習はgoto消えた後でも止まりました。
ジル 'SO-悪であるのをやめる

8

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

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.