Linux 上で Bash スクリプトを 使い始める場合は、基本をしっかりと理解しておくと役に立ちます。これらは、より深い知識とより高度なスクリプト スキルの基礎となります。
スクリプトを実行可能にしてください。
シェルがスクリプトを実行するには、スクリプトに実行可能 ファイルの アクセス許可セットが必要です。これがなければ、スクリプトは単なるテキスト ファイルになります。このファイルは依然としてテキスト ファイルですが、シェルはそれに命令が含まれていることを認識し、スクリプトが起動されるとその命令を実行しようとします。
スクリプトを作成する最大のポイントは、スクリプトが実行されることです。そのため、最初の基本的なステップは、スクリプトが実行可能であると見なされるべきであることを Linux に知らせる方法を知ることです。
chmod
コマンドを使用すると、ファイルのアクセス許可を設定できます。実行権限は +x フラグで設定できます。
chmod +x script1.sh
これを各スクリプトに対して行う必要があります。 「script1.sh」をスクリプトの名前に置き換えます。
1. その奇妙な最初の行は何ですか?
スクリプトの最初の行は、そのスクリプトを実行するためにどのインタプリタを呼び出す必要があるかをシェルに指示します。最初の行は、ハッシュバンとも呼ばれるシバン「#!」で始まる必要があります。 「#!」この行には、スクリプトが作成されたインタープリタのパスと名前が含まれていることをシェルに伝えます。
Bash で実行するスクリプトを作成した場合、そのスクリプトが別のシェルによって解釈されることを望まないため、これは重要です。非互換性が存在する可能性があります。 Bash には、ほとんどのシェルと同様に、他のシェルにはない、または異なる方法で実装される独自の構文と機能の癖があります。
スクリプトを実行すると、現在のシェルがスクリプトを開き、そのスクリプトの実行にどのシェルまたはインタプリタを使用するかを決定します。次に、そのシェルを起動し、スクリプトをシェルに渡します。
#!/bin/bash
echo $SHELL で実行中
このスクリプトの最初の行は、「このスクリプトを実行するには、/bin/bash にあるインタープリタを使用します。」と読み取れます。
スクリプト内の唯一の行は
$SHELL
環境変数に保持されている値を端末画面に書き込みます。これにより、スクリプトの実行に Bash が使用されたことが確認されます。
./script1.sh
ちょっとしたお座敷芸として、選択したインタプリタにスクリプトが渡されることを実証できます。
#!/ビン/猫
テキストのすべての行が cat コマンドに渡されます。
ターミナルウィンドウに表示されます。それには、
シバンライン。
スクリプト2.sh
このスクリプトは現在のシェルによって起動され、
cat
コマンド
に渡されます。
cat
コマンドはスクリプトを「実行」します。
このようにシバンを書くと、ターゲット マシン上のシェルまたは他のインタープリターがどこにあるかを知っていると想定されます。そして99%の場合、それで大丈夫です。しかし、賭けをヘッジして次のようにシバンを書くことを好む人もいます。
#!/usr/bin/env bash
echo $SHELL で実行中
スクリプト3.sh
スクリプトが起動されると、シェルは指定されたシェルの場所を検索します。シェルがたまたま標準以外の場所にある場合、このタイプのアプローチにより「不正なインタープリター」エラーを回避できます。
聞くな、彼は嘘をついている!
Linux では、猫の皮を剥ぐ方法や作者の間違いを証明する方法は常に複数あります。完全に事実に基づいて言うと、スクリプトをシバンなしで実行可能にせずに実行する方法があります。
スクリプトを実行するシェルを起動し、そのスクリプトを コマンド ライン パラメータとして渡すと、実行可能かどうかに関係なく、シェルが起動してスクリプトを実行します。コマンドラインでシェルを選択するため、シバンは必要ありません。
これがスクリプト全体です:
echo "私は $SHELL によって処刑されました"
ls
使用して、スクリプトが実際に実行可能でないことを確認し、スクリプトの名前で Bash を起動します。
ls
bash script4.sh
スクリプトを実行するために特別に起動されたシェルではなく、現在のシェルでスクリプトを実行する方法もあります。単一のピリオド「
.
」に短縮できる
source
コマンドを使用すると、スクリプトは現在のシェルによって実行されます。
したがって、シバンを使用せず、実行可能ファイルのアクセス許可を使用せず、別のシェルを起動せずにスクリプトを実行するには、次の コマンド のいずれかを使用できます。
ソース script4.sh
。スクリプト4.sh
これは可能ですが、一般的な解決策としてはお勧めできません。欠点もあります。
スクリプトにシバンが含まれていない場合、それがどのシェル用に書かれたのかわかりません。 1年後には覚えているでしょうか?また、スクリプトに実行可能権限が設定されていないと、
ls
コマンドは
それを実行可能ファイルとして識別せず、スクリプトとプレーン テキスト ファイルを区別するために色を使用しません。
2. テキストの印刷
端末にテキストを書き込むことは一般的な要件です。ちょっとした視覚的なフィードバックは大いに役立ちます。
単純なメッセージの場合は、
echo
コマンドで十分です
。これにより、テキストの一部の書式設定が可能になり、変数も操作できるようになります。
#!/bin/bash
echo これは単純な文字列です。
echo “これは「一重引用符」を含む文字列なので、二重引用符で囲みます。
echo “これはユーザー名を出力します:” $USER
echo -e “-e オプションを使用すると、\n書式設定ディレクティブを\n使用して文字列を分割できます。”
./script5.sh
printf
コマンドを使用する
と、柔軟性が高まり、数値変換などの書式設定機能が向上します。
このスクリプトは、3 つの異なる基数を使用して同じ数値を出力します。 16 進数バージョンも、先行ゼロと 3 桁の幅で大文字で印刷されるようにフォーマットされています。
#!/bin/bash
printf “10 進数: %d、8 進数: %o、16 進数: %03X\n” 32 32 32
./script6.sh
echo
とは異なり、「
\n
」トークンで新しい行を開始するように
printf
に指示する必要があることに注意してください。
3. 変数の作成と使用
変数を使用すると、プログラム内に値を保存し、その値を操作して使用できます。 独自の変数を作成することも、システム値として環境変数を使用することも できます。
#!/bin/bash
millennium_text=”ミレニアムからの年数:”
current_time=$( 日付 ‘+%H:%M:%S’ )
todays_date=$( 日付 ‘+%F’ )
year=$( 日付 ‘+%Y’ )
echo “現在時刻:” $current_time
echo “今日の日付:” $todays_date
years_since_Y2K=$(( 年 – 2000 ))
エコー $millennium_text $years_since_Y2K
このスクリプトは、
millennium_text
という文字列変数を作成します。テキスト行が保持されます。
次に、3 つの数値変数を作成します。
-
current_time変数は、スクリプトが実行された時刻に初期化されます。 -
todays_date変数は、スクリプトが実行される日付に設定されます。 -
year変数は現在の年を保持します。
変数に格納されている値にアクセスするには、その名前の前にドル記号「$」を付けます。
./script7.sh
スクリプトは時刻と日付を出力し、ミレニアムから経過した年数を計算し、これを
years_since_Y2K
変数に保存します。
最後に、
millennium_text
変数に含まれる文字列と
years_since_Y2K
に格納されている数値を出力します。
4. ユーザー入力の処理
スクリプトが使用する値をユーザーが入力できるようにするには、ユーザーのキーボード入力をキャプチャできる必要があります。 Bash
read
コマンドを使用すると、まさにそれが可能になります。以下に簡単な例を示します。
#!/bin/bash
echo “数字を入力して「Enter」を押してください”
user_number1 を読み取ります。
echo “別の番号を入力して「Enter」を押してください”
user_number2 を読み取ります。
printf “入力しました: %d と %d\n” $user_number1 $user_number2
printf “これらを合計すると: %d\n” $(( user_number1 + user_number2))
スクリプトは 2 つの数字の入力を求めます。これらはキーボードから読み取られ、
user_number1
と
user_number2
2 つの変数に保存されます。
スクリプトは数値を端末ウィンドウに出力し、それらを加算して合計を出力します。
./script8.sh
-p
(プロンプト) オプションを使用して、プロンプトを
read
コマンドに結合できます。
#!/bin/bash
read -p “数字を入力して「Enter」を押してください。” user_number1;
read -p “別の番号を入力して \”Enter\” を押します ” user_number2;
printf “入力しました: %d と %d\n” $user_number1 $user_number2
printf “これらを合計すると: %d\n” $(( user_number1 + user_number2))
これにより、内容がすっきりして読みやすくなります。読みやすいスクリプトは、デバッグも簡単です。
./script9.sh
スクリプトの動作が少し異なります。ユーザー入力はプロンプトと同じ行にあります。
ターミナル ウィンドウにエコーせずにキーボード入力をキャプチャするには、
-s
(サイレント) オプションを使用します。
#!/bin/bash
read -s -p “シークレット PIN を入力し、\”Enter\” を押します。 ” secret_PIN;
printf “\nシーッ…それは %d\n” $secret_PIN
./script10.sh
入力値は取得され、
secret_PIN
という変数に保存されますが、ユーザーが入力しても画面にエコー表示されません。その後それをどうするかはあなた次第です。
5. パラメータの受け入れ
スクリプトを入力を待機させるよりも、ユーザー入力をコマンド ライン パラメーターとして受け入れる方が便利な場合があります。スクリプトに値を渡すのは簡単です。これらは、他の変数であるかのように、スクリプト内で参照できます。
最初のパラメーターは変数
$1
になり、2 番目のパラメーターは変数
$2
になり、以下同様になります。変数
$0
は常にスクリプトの名前が保持され、変数
$#
コマンド ラインで指定されたパラメーターの数が保持されます。変数
$@
、すべてのコマンド ライン パラメーターを含む文字列です。
#!/bin/bash
printf “このスクリプトの名前は次のとおりです: %s\n” $0
printf “%d コマンド ライン パラメータを使用しました\n” $#
# 変数をループします
“$@” のパラメータの場合;する
「$param」をエコーする
終わり
echo “パラメータ 2 は次のとおりでした:” $2
このスクリプトは
$0
と
$#
を使用して情報を出力します。次に、
?@
を使用してすべてのコマンド ライン パラメーターをループします。
$2
を使用して、単一の特定のパラメーター値にアクセスする方法を示します。
./script11.sh
複数の単語を引用符「”」で囲むと、それらの単語が 1 つのパラメーターに結合されます。
6. ファイルからのデータの読み取り
ファイルからデータを読み取る方法を知ることは、優れたスキルです。 Bash では while ループを使用して これを行うことができます。
#!/bin/bash
行数=0
while IFS=” 読み取り -r LinefromFile || [[ -n “${LinefromFile}” ]];する
((LineCount++))
echo “行 $LineCount を読み取っています: ${LinefromFile}”
完了 < “$1”
スクリプトで処理するファイルの名前をコマンド ライン パラメーターとして渡します。これが唯一のパラメータとなるため、スクリプト内では
$1
ファイル名を保持します。そのファイルを
while
ループにリダイレクトしています。
while
ループは、
IFS=''
割り当てを使用して、内部フィールド区切り文字を空の文字列に設定します。これにより、
read
コマンドが空白で行を分割するのを防ぎます。行末のキャリッジ リターンのみが行の真の終端とみなされます。
[[ -n "${LinefromFile}" ]]
句は、ファイルの最後の行が復帰で終わらない可能性を考慮します。そうでない場合でも、最後の行は正しく処理され、通常の POSIX 準拠の行として扱われます。
./script12.sh トゥインクル.txt
7. 条件付きテストの使用
スクリプトでさまざまな条件に対してさまざまなアクションを実行する場合は、条件付きテストを実行する必要があります。 二重括弧のテスト構文は、 最初は圧倒的な数のオプションを提供します。
#!/bin/bash
価格=$1
if [[ 価格 -ge 15 ]];
それから
エコー「高すぎる」
それ以外
エコー「買って!」
フィ
Bash は、 ファイルが存在するかどうか 、ファイルから読み取ることができるかどうか、ファイルに書き込むことができるかどうか、ディレクトリが存在するかどうかなどを判断できる 比較演算子 のセット全体を提供します。
また、等しい
-qe
、大きい
-gt
、以下であるか等しい
-le
などの数値テストもありますが、おなじみの
==
、
>=
、
<=
表記も使用できます。
./script13.sh 13
./script13.sh 14
./script13.sh 15
./script13.sh 16
8. for ループの力
アクションを何度も繰り返すには、ループを使用するのが最適です。
for
ループを使用
すると、ループを何度も実行
できます。これは、特定の数値までである場合もあれば、ループが項目のリストを完了するまでである場合もあります。
#!/bin/bash
for (( i=0; i<=$1; i++ ))
する
echo “C スタイルの for ループ:” $i
終わり
{1..4} の i について
する
echo “範囲を指定した for ループ:” $i
終わり
「ゼロ」「ワン」「ツー」「スリー」の私のために
する
echo “単語のリストを含む for ループ:” $i
終わり
ウェブサイト=「オタクのやり方」
$website の私のために
する
echo “単語のコレクションを含む for ループ:” $i
終わり
これらのループはすべて
for
ループですが、さまざまな種類のループ ステートメントとデータを処理します。
./script14.sh 3
最初のループは、古典的な C スタイル
for
ループです。ループ カウンタ
i
ゼロに初期化され、ループの各サイクルごとに増加します。
i
の値が
$1
に保持されている値以下である間、ループは実行を続けます。
2 番目のループは 1 から 4 までの数値の範囲を処理します。3 番目のループは単語のリストを処理します。処理すべき単語がさらにある間、ループが繰り返されます。
最後のループは、文字列変数内の単語のリストを処理します。
9. 機能
関数を使用すると、コードのセクションを、スクリプト内のどこからでも呼び出すことができる名前付きルーチンにカプセル化できます。
ファイルから行を読み取るスクリプトで、各行に対して何らかの処理を実行したいとします。そのコードを関数内に含めると便利です。
#!/bin/bash
行数=0
関数 count_words() {
printf “%d 行目に %d 語\n” $(echo $1 | wc -w) $2
}
while IFS=” 読み取り -r LinefromFile || [[ -n “${LinefromFile}” ]];する
((LineCount++))
count_words “$LinefromFile” $LineCount
完了 < “$1”
count_words “これはループに含まれていません” 99
count_words
という関数を追加して、ファイル読み取りプログラムを変更しました。これは使用する前に定義されています。
関数定義は
function
という単語で始まります。これに関数の一意の名前が続き、その後に括弧「
()
」が続きます。関数の本体は中括弧「{}」で囲まれています。
関数定義によってコードが実行されることはありません。関数が呼び出されるまで、関数内の何も実行されません。
count_words
関数は、テキスト行の単語数と行番号を出力します。これら 2 つのパラメータは、パラメータがスクリプトに渡されるのと同じように関数に渡されます。最初のパラメーターは関数変数
$1
になり、2 番目のパラメーターは関数変数
$2
になり、以下同様です。
while
ループはファイルから各行を読み取り、それを行番号とともに
count_words
関数に渡します。そして、スクリプト内のさまざまな場所から関数を呼び出せることを示すために、
while
ループの外側でもう一度関数を呼び出します。
./script15.sh トゥインクル.txt
学習曲線を恐れないでください
スクリプト作成はやりがいがあり便利ですが、始めるのは困難です。再利用可能なテクニックをいくつか習得すれば、価値のあるスクリプトを比較的簡単に作成できるようになります。その後、より高度な機能を検討できます。
走る前に歩いて、時間をかけて旅を楽しみましょう。





