シェルのコマンドの前の「!」の意味は?
質問
エクスクラメーションマークで始まるシェルコマンド(シェルスクリプトの一部)は何のためにあるのですか?
具体的な例です。
foo.shで。
#!/usr/bin/env bash
set -e
! docker stop foo
! docker rm -f foo
# ... other stuff
スペースがないとエクスクラメーションマークが履歴の置き換えに使われるのは知っているし
! <expression>
によると
のマニュアルページ
は " を評価するために使用することができます。
expr が false ならば真
を評価することができます。しかし、例のコンテキストでは、それは私には意味をなさない。
どのように解決するのですか?
TL;DR: これは、単に
set -e
フラグを使用する特定の行でバイパスしているだけです。
にaddを追加する。 hek2mgl さんの正しい有用な回答 .
ありますね。
set -e
! command
Bashリファレンスマニュアル → パイプライン を記述します。
パイプラインの各コマンドは、それ自身のサブシェルで実行されます。パイプラインの終了ステータスは、パイプラインの最後のコマンドの終了ステータス (...) です。 予約語 '!' がパイプラインの前にある場合、終了ステータスは終了ステータスの論理的否定となります。 となります。シェルはパイプラインの全てのコマンドが終了するのを待ってから値を返します。
これはつまり
!
をコマンドの前に置くことは、そのコマンドの終了ステータスを否定していることになります。
$ echo 23
23
$ echo $?
0
# But
$ ! echo 23
23
$ echo $?
1
または
$ echo 23 && echo "true" || echo "fail"
23
true
$ ! echo 23 && echo "true" || echo "fail"
23
fail
終了ステータスはいろいろな意味で便利です。スクリプトの中で
set -e
を使うと、コマンドがゼロ以外のステータスを返すたびにスクリプトを終了させます。
このように、あるとき
set -e
command1
command2
もし
command1
が 0 以外のステータスを返した場合、スクリプトは終了し、次の
command2
.
しかし、興味深い点として、以下のように記述されていることもあります。 4.3.1 集合ビルトイン :
-e
パイプライン (パイプライン参照) が、単一の単純コマンド (単純コマンド参照)、リスト (リスト参照)、複合コマンド (複合コマンド参照) からなる場合、0 以外のステータスを返したら直ちに終了します。 シェルが終了しない 失敗したコマンドが while または until キーワードの直後のコマンドリスト、 if 文のテストの一部、最後の && または || に続くコマンドを除く && または || リストで実行されるコマンドの一部、最後のコマンドを除くパイプラインのコマンド、 または でコマンドの戻りステータスが反転している場合、! . サブシェル以外の複合コマンドが、-e を無視している間にコマンドが失敗したために 0 以外の状態を返した場合、シェルは終了しません。ERRのトラップが設定されている場合、シェルが終了する前に実行されます。
これらをすべて考慮した上で、あるときは
set -e
! command1
command2
何をしているかというと、バイパスするために
set -e
フラグを
command1
. なぜ?
-
もし
command1
が正しく実行されれば、0 のステータスを返します。!
はそれを否定しますがset -e
によって終了を引き起こすことはありません。なぜなら、それは上記のように! -
もし
command1
が失敗すると、0 以外のステータスを返します。!
はそれを否定するので、その行は結局ゼロのステータスを返し、スクリプトは通常通り続行されます。
関連
-
Apache の一般的な設定エラー
-
[解決済み] Bashスクリプトのソースディレクトリをスクリプト自体から取得するにはどうすればよいですか?
-
[解決済み] プログラムの実行やシステムコマンドの呼び出しはどのように行うのですか?
-
[解決済み] Bashシェルスクリプトでディレクトリが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] シェルで、「2>&1」はどういう意味ですか?
-
[解決済み] Bashでコマンドの出力に変数を設定するにはどうすればよいですか?
-
[解決済み] find .コマンドでディレクトリを除外する方法
-
[解決済み] LinuxのシェルスクリプトでYes/No/Cancelの入力を促すにはどうしたらいいですか?
-
[解決済み] Bashシェルスクリプトの入力引数の存在確認
-
[解決済み] Git上でシェルコマンドを実行する際に使用するSSH-keyの秘密鍵を指定する方法は?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
ゼロからLinuxのisoイメージを作る方法(グラフィックチュートリアル)
-
deepin20のファイルを共有する方法を教えてください。Windowsでdeepinファイルを共有するためのヒント
-
deepinシステムのバージョン番号を見るには?deepinシステムのバージョン情報を見るコツ
-
Kali Linuxのマウスを左利き用に設定する方法は?Linuxマウス左利き操作選択方法
-
TclError: 表示名がなく、$DISPLAY環境変数もない。
-
GCCのバージョンによる浮動小数点演算の例外発生
-
[解決済み] IOCTL Linuxデバイスドライバ [終了しました]
-
[解決済み] cronは内部でどのようにジョブをスケジューリングしているのですか?
-
[解決済み] 出力をファイルや標準出力にリダイレクトする方法
-
[解決済み] Linuxのディレクトリ内のファイルを再帰的にカウントする