Bash(:)でnoopを検索しましたが、良い情報を見つけることができませんでした。この演算子の正確な目的または使用例は何ですか?
私はフォローしようとしましたが、私にとってはこのように機能しています:
[mandy@root]$ a=11
[mandy@root]$ b=20
[mandy@root]$ c=30
[mandy@root]$ echo $a; : echo $b ; echo $c
10
30
リアルタイムでのこの演算子の使用事例、またはそれを使用することが義務付けられている場所をお知らせください。
歴史的な理由により多くあります。コロンの組み込み:
は、true
とまったく同じです。戻り値が重要な場合、たとえば無限ループでtrue
を使用するのが伝統的です。
while true; do
echo 'Going on forever'
done
シェルの構文にコマンドが必要だが、何もする必要がない場合、:
を使用するのが伝統的です。
while keep_waiting; do
: # busy-wait
done
:
ビルトインは Thompson Shell にまでさかのぼり、 nix v6 では present でした。 :
は、Thompson Shellのgoto
ステートメントのラベルインジケーターでした。ラベルは任意のテキストにすることができるため、:
はコメントインジケータとして2重になります(goto comment
がない場合、: comment
は事実上コメントです)。 Bourne Shell にはgoto
がありませんでしたが、:
は保持されました。
:
を使用する一般的なイディオムは : ${var=VALUE}
です。これは、var
が未設定の場合はVALUE
に設定し、var
の場合は何も行いませんすでに設定されていました。このコンストラクトは変数置換の形式でのみ存在し、この変数置換は何らかの形でコマンドの一部である必要があります:no-opコマンドはうまく機能します。
コロンビルトインはどのような目的で機能しますか? も参照してください。
すべてのコードをコメントアウトするときの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
:
を使用して、成功するが何もしないコマンドを提供します。この例では、「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
set- e
を使用する場合、|| :
はnotが失敗した場合にスクリプトを終了するための優れた方法です(明示的にパスします)。
alias
引数を無視引数を取らないエイリアスが必要な場合があります。 :
を使用して実行できます:
> alias alert_with_args='echo hello there'
> alias alert='echo hello there;:'
> alert_with_args blabla
hello there blabla
> alert blabla
hello there
1つの用途は、複数行のコメントとして、またはコードをhereファイルと組み合わせて使用して、テスト目的でコードの一部をコメントアウトすることです。
_: << 'EOF'
This part of the script is a commented out
EOF
_
EOF
を引用符で囲むことを忘れないでください。そうすれば、$(foo)
のように内部のコードが評価されません。また、NOTES
、SCRATCHPAD
、またはTODO
などの直感的なターミネーター名を使用する価値があります。
私の2つ。
:
の非常にファンキーなアプリケーションは、 bashスクリプトにPODコメントを埋め込む のためです。そのため、manページをすばやく生成できます。もちろん、最終的にはPerlでスクリプト全体を書き直します;-)
これは、実行時に関数をバインドするための一種のコードパターンです。 F.i.、特定のフラグが設定されている場合にのみ何かを行うデバッグ機能があります:
#!/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
No-op句を使用すると、コードが読みやすくなる場合があります。
それは意見の問題かもしれませんが、ここに例があります。 2つのUNIXパスを使用して機能する関数を作成したとします。あるパスから別のパスにcdするのに必要な「パスの変更」を計算します。パスは両方とも「/」で開始する必要があるという制限を関数に設定しますOR両方ではいけません。
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回。頻繁に発生するため、注意してください。 (言語に関係なく)コードの可読性が向上すると思うとき、私はそれを使うことをためらいません。
この回答 に多少関連しているため、このno-opは polyglot スクリプトをハッキングするのにかなり便利です。たとえば、bashとvimscriptの両方に有効なコメントを次に示します。
":" # this is a comment
":" # in bash, ‘:’ is a no-op and ‘#’ starts a comment line
":" # in vimscript, ‘"’ starts a comment line
もちろん、true
も使用したかもしれませんが、:
句読点記号であり、無関係な英語の単語ではないことは、それが構文トークンであることを明確にします。
whyについては、誰かがポリグロットスクリプトを書くなどのトリッキーなことをするでしょう(クールであることに加えて):それは、ファイルX
はファイルY
を参照しています。
そのような状況では、両方のスクリプトを単一のポリグロットファイルに組み合わせることで、X
へのパスを決定するためのY
での作業が回避されます(単に"$0"
)。さらに重要なことは、プログラムの移動や配布がより便利になることです。
一般的な例。シェバンにはよく知られた長年の問題があります:ほとんどのシステム(LinuxとCygwinを含む)はone引数のみを許可します通訳者に渡されます。次のシバン:
#!/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"
。ただし、そのセットアップはかなりのものであったため、文字列でインライン化するのはひどいことでした(可能な場合)。したがって、より良い解決策は、構成ファイルにin extensoと記述し、Vimに-S "/path/to/file"
。したがって、ポリグロットbash/vimscriptファイルになりました。
別の成功に連鎖させたいコマンドがあるとします:
cmd="some command..."
$cmd
[ $? -eq 0 ] && some-other-command
ただし、条件付きでコマンドを実行し、実行されるコマンドを表示したい場合(dry-run):
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 || :