高級言語、スクリプト言語、インタプリタ言語:xxx.sh、一般的に bash に基づく
コース内容#
最初のシェルスクリプト#
#!/bin/bash
#コメント
echo "Hello"
- 最初の行 #! はインタプリタを指定し、最初の行でのみ有効
- コメント:"#"
変数#
a=123
a=hello
a=`pwd`
PATH=${PATH}:path # 変数の後に文字列を付けることができ、文字列を直接結合できる
# 【注意】":a"には特別な意味があり、現在のパスを指す
特殊変数#
位置変数
結果:
-
-
$n:n>9 の場合、大括弧で囲む必要がある
-
$@ と $* の違いは:渡された引数がそれぞれ二重引用符で囲まれ、かつ $ 変数も二重引用符で囲まれている場合、"$@" はすべての引数を分ける【一般的な場合】が、"$*" はすべての引数を一つの全体として扱う
- for...in を使用するとわかる、詳細はシェル特殊変数:Shell $0, $#, $*, $@, $?, $$ とコマンドライン引数——C 言語中文網
-
$#:$0 はカウントしない
状態変数
- $?:【前の】コマンドの実行結果、0—— 成功、非 0—— 不成功
-
- スクリプトがコマンドの成功を自動的に判断するのに便利
-
- $$、$!:現在のプロセス、最後に実行されたバックグラウンドプロセスの PID、一般的に自動化テストや複数スクリプトの相互作用のシーンで使用される
入出力#
- 入力:read
-
- -p:フレンドリーなプロンプトを表示、bash で使用する必要がある
- -s:サイレントモード
- -t:入力待機時間、タイムアウト終了(単位:s)
-
- 出力:echo
- -e:エスケープを有効にする
- 出力:printf
- C 言語の printf に非常に似ている!
-
- [PS] ! と \n を一緒に使うと特別な意味があるため、分ける必要がある
- bash では分ける必要がある
- zsh では分けることができ、または \ でエスケープすることができる
- 一般的に特殊記号—— 菜鳥教程には注意が必要!
関数#
-
-
引数はない
-
定義:書き方はいくつかあり、function、()、{} の組み合わせ、第 3 の方法は C 言語の書き方に似ている
-
呼び出し:関数名 引数...
-
- function を追加すると読みやすくなる
-
-
❗【注意】シェルの関数 return の戻り値には制限があり、範囲は 0-255 で、オーバーフローすると循環換算される
フロー制御#
do——done、if——then——fi、case——esac
【重点】TEST 式⭐#
- タイプを判断できる:文字列、整数、ファイル
- ❗ 【注意】条件が真のとき、0 を返し、そうでない場合は非 0 を返す
- Linux のコマンドの戻り値も同様で、0 が成功を表す
- [PS]
- STRING1 = STRING2 も == を使うことができる【後者を推奨、二つの中括弧 [[]] がサポート】
- -G FILE:ファイルが存在し、有効なグループ ID に所有されている
- グループが解散された場合、そのグループが管理するファイルのグループ ID は無効になる
- 詳細は man マニュアルを参照:man test
分岐構造#
if
-
-
if は二つの中括弧 [[]] の書き方を使用し、高度で、TEST 式との互換性がより良い
- 一つの中括弧 [ ] は何年も前の書き方で、推奨されず、二つの中括弧を使用する
- 参考:Linux Shell における ()、(())、[]、[[]]、{} の役割—— ブログ
case
-
-
セミコロン;;は必ず必要!break に相当し、break を加えた場合も必要
-
デフォルトの状況には *) を使用できる
-
case はあまり使用されず、一般的にメニューを作成するために使用され、if よりも美しい
ループ構造#
for
-
seq を利用してシーケンスを生成
-
-
ls のマッチングルールを利用
-
-
for の二つの形式
-
-
二重小括弧 (()) の中の内容は C 言語の演算規則に従う限り、変数の前に $ を付けずに書くことができ、i++ と書くことができ、通常は ++ を使用できない
while
-
-
同様に test 式が適用される
-
num 変数を初期化しないと
- 最初の echo $num の時、$num は空値で、空行として表示される
- 後の + 1 に遭遇したとき、システムはそれを整数型として判定し、初めて整数として使用される
until
-
-
while との唯一の違いは:until は停止条件を書き、while はループ条件を書く
配列#
-
-
配列の代入【方法①】と呼び出し
-
-
【一般的な配列操作】は配列要素のインデックスを出力することもできる、後で見て
-
-
配列の宣言:declare -a num、読みやすくするため、宣言しなくてもよい【弱い型の言語】
-
代入【方法②、③】
- num[2]=10 num[5]=7 num[100]=3.2.4
- num=(1 a b 10)
-
配列要素は必ずしも連続して代入する必要はなく、任意の型を持つことができる
- 【一般的な配列操作】加!:すべての配列要素に対応するインデックスを出力し、連続していないことがわかる
【その他の配列操作】
-
-
+=:追加
-
unset:配列または要素を削除する【インデックスで削除】
-
[PS] 代入方法③は複数の空白も一つの区切り文字として扱う
応用
-
-
ファイル名のリストを保存するために使用できる
-
【注意】代入方法③で配列に代入する際は空白を区切り文字として使用するため、ファイル名に空白が含まれている場合は特別な処理が必要
-
【PS】素数篩、線形篩
授業中の練習#
1~100 の偶数の合計#
-
-
$[ ] は整数演算に使用できる
-
seq は効率がやや低い
力任せに素数を求める#
-
-
関数の return 値
- $? を通じて得られ、関数を呼び出した後に echo $? を実行すればよいが、return 値には範囲制限がある 0~255!
- コマンド置換子 `` を使って得る
-
ループ変数 i の衝突問題に注意:ローカル変数を定義する
-
🆒プログラムのデバッグ
- 習慣:適切な echo 出力
- グローバルデバッグ:bash -x *.sh
- ローカルデバッグ:set -x [デバッグコード領域] set +x
素数篩#
-
-
方法一は素数を操作するのに便利で、出力時に判断を減らすことができる
-
方法二は合成数を操作することもできる
【力任せ法、素数篩の 2 つの方法の効果比較】2~10000 の素数の合計を求める
- 9.prime.sh 力任せ法 —— 10.prime.sh 素数篩
追加知識点#
- .sh スクリプトは直接 bash または source で実行でき、./ を使用するには実行権限が必要
- source、sh、bash、./ の違い——cnblogs
- set -x はシェルデバッグを有効にする
- シェルコマンド置換:コマンドの出力結果を変数に代入する——C 言語中文網
- $() はネストをサポートし、バッククオート `` はサポートしない
- $() は Bash でのみ有効【zsh、sh もサポートしているようだ】、バッククオート `` は多くのシェルで使用可能
- 二重小括弧 (()) の中の内容
- C 言語の演算規則に従う限り、変数の前に $ を付けずに書くことができ、i++ と書くことができ、通常は ++ を使用できない
- ⭐シェルでは、変数がまだ定義されていない場合、その値は空であり、echo 出力は空行として表示される
- ⭐空白問題【厳密】
- 代入文:= の左右には空白があってはならない
- TEST 式関連:[[]] の両端には必ず空白が必要
- 変数名 i について、$i と_i を結合したい場合、$i_i と書くと変数 i_i を探しに行くため、${i}_i を使用する必要がある
ヒント#
- シェルスクリプトを書く際
- 性能をあまり考慮せず、単純に数学計算の効率は低い
- 問題を迅速に解決するために、すべてのタスクのフローを計画するために使用する
- 操作の前に【バックアップ】操作を追加することを忘れない
- 一般的にはシステムに作業をさせることが難しく、特定のプログラムに作業をさせることが難しい
- プログラムには一般的に独自のパラメータ設定があるが、普遍性はない
- API は一般にサービスを指す
- ⭐シェルスタイルガイド——Google オープンソースプロジェクトスタイルガイド —— シェルプログラミング規範
- シェルスクリプトの複数行コメントと単行コメントの方法—— ブログ
:<<!
[コメントするコード]
!
- let—— 菜鳥教程、便利な構文を理解することができる