BASHの基礎。 パート2

BASHの基礎。 パート2
記事間の大きな遅れをおforび申し上げますが、このセッションは最も都合の悪い瞬間に感じられます:)
前の記事のコメントで表明されたコメント、批判、追加をありがとう。
約束どおり、この部分はサイクル、数学演算、外部コマンドの使用に専念します。
始めましょう。


サイクル。 For-inループ


for-in演算子は、リストにリストされている値に1つずつアクセスするために使用されます。 リスト内の各値は変数に割り当てられます。
構文は次のとおりです。
for in _
do

done

小さな例を考えてみましょう:
#!/bin/bash
for i in 0 1 2 3 4 # $i 0 4
do
echo "Console number is $i" >> /dev/pts/$i # /dev/pts/$i( ) "Console number is $i"
done #
exit 0

この例を実行すると、最初の5つの仮想コンソール(端末)に番号付きの行が表示されます。 リストの値は変数$ iに1つずつ代入され、ループはこの変数の値を処理しています

サイクル。 whileループ。


whileループはfor-inループよりも複雑で、ある式が真(戻りコード= 0)になるまでコマンドを繰り返すために使用されます。
演算子の構文は次のとおりです。
while
do

done

次の例では、サイクルの動作の例を検討します。
#!/bin/bash
again=yes # "yes" again
while [ "$again" = "yes" ] # , $again "yes"
do
echo "Please enter a name:"
read name
echo "The name you entered is $name"

echo "Do you wish to continue?"
read again
done
echo "Bye-Bye"

そして今、スクリプトの結果:
ite@ite-desktop:~$ ./bash2_primer1.sh
Please enter a name:
ite
The name you entered is ite
Do you wish to continue?
yes
Please enter a name:
mihail
The name you entered is mihail
Do you wish to continue?
no
Bye-Bye


ご覧のとおり、ループは「はい」以外の何かを導入するまで実行されます。 doとdoneの間で、任意の構造、演算子などを記述でき、それらはすべてループで実行されますが、式変数を変更せずにコマンドを実行する場合は、このループに注意する必要があります。無限ループに入ります。
真実の状態について。 しばらくすると、if-then-else条件ステートメントのように、リターンコードを返す式またはコマンドを挿入でき、ループはリターンコード= 0になるまで実行されます! 演算子「[」はテストコマンドに類似しており、渡された条件の有効性をチェックします。

別の例を考えてみましょう。AdvancedBash Scriptingという本から取りました。 私は彼が本当に好きでした:)が、私はそれを少し単純化しました。 この例では、別のタイプのUNTIL-DOループを紹介します 。 これは、WHILE-DOサイクルのほぼ完全な類似物であり、これまでに実行されているのは一部の式のみです。
以下に例を示します。
#!/bin/bash
echo " : "
read dividend
echo " : "
read divisor

dnd=$dividend # dividend divisor,
# , ..
#
dvs=$divisor
remainder=1

until [ "$remainder" -eq 0 ]
do
let "remainder = dividend % divisor"
dividend=$divisor
divisor=$remainder
done

echo " $dnd $dvs = $dividend"

スクリプトの結果:
ite@ite-desktop:~$ ./bash2_primer3.sh
:
100
:
90
100 90 = 10


数学演算


Letコマンド。
letコマンドは、数値と変数の算術演算を実行します。
入力した数値に対していくつかの計算を実行する小さな例を考えてみましょう。
#!/bin/bash
echo " a: "
read a
echo " b: "
read b

let "c = a + b" #
echo "a+b= $c"
let "c = a / b" #
echo "a/b= $c"
let "c <<= 2" # c 2
echo "c 2 : $c"
let "c = a % b" # a b
echo "$a / $b. : $c "

実行結果:
ite@ite-desktop:~$ ./bash2_primer2.sh
a:
123
b:
12
a+b= 135
a/b= 10
c 2 : 40
123 / 12. : 3

ご覧のとおり、複雑なことは何もありませんが、数学演算のリストは標準です。
+-追加
--減算
*-乗算
/-除算
**-べき乗
%-モジュール(モジュロ除算)、除算の剰余
letを使用すると、算術コマンドの省略形を使用できるため、使用する変数の数を減らすことができます。 たとえば、a = a + bはa + = bと同等です。

シェルスクリプトを記述するときに外部プログラムを操作する


まず、少し役に立つ理論。
フローのリダイレクト。

bash(他の多くのシェルと同様)には、組み込みファイル記述子があります:0(stdin)、1(stdout)、2(stderr)。
stdout-標準出力。 プログラムが表示するすべてを取得します
stdin-標準入力。 ユーザーがコンソールに入力するのはこれだけです
stderr-標準エラー出力。
これらの記述子を使用した操作の場合、特殊文字があります:>(出力リダイレクト)、<(入力リダイレクト)。 それらを操作することは難しくありません。 例:
猫/ dev /ランダム> / dev / null
cat / dev / randomの出力を/ dev / nullにリダイレクトします(絶対に役に立たない操作:)))または
ls -la>リスト
現在のディレクトリの内容をリストファイルに書き込みます(すでに便利です)
ファイルに追加する必要がある場合(「>」を使用する場合は置き換えられます)、「>」ではなく「>>」を使用する必要があります。
sudo <my_password
sudoがパスワードを要求すると、キーボードから入力したかのようにmy_passwordファイルから取得されます。
プログラムの操作中に発生した可能性のあるエラーのみをファイルに書き込む必要がある場合は、次を使用できます。
./program_with_error 2> error_file
「>」の前の数字2は、ハンドル2(stderr)に該当するものすべてをリダイレクトする必要があることを意味します。
stderrにstdoutへの書き込みを強制する必要がある場合は、これをトレースできます。 方法:
./program_with_error 2>&1
文字「&」は、ハンドル1(stdout)へのポインターを意味します
(デフォルトでは、stderrはユーザーが作業しているコンソールに書き込みます(以前にディスプレイに書き込みます)。

2.コンベア。

パイプラインは、Bashコンソールを操作するための非常に強力なツールです。 構文は簡単です:
1 | 2 1 | 2コマンド1の出力がコマンド2の入力に送信されることを意味します
パイプラインをチェーンにグループ化し、ファイルへのリダイレクトを使用して出力できます。次に例を示します。
ls -la | grep "hash" | sort> sortilg_list
ls -laコマンドの出力はgrepコマンドに渡されます。grepコマンドは、単語hashを含むすべての行を選択し、sortコマンドをsortに渡します。sortコマンドは、sort_listファイルに結果を書き込みます。 すべてが非常に明確でシンプルです。

ほとんどの場合、Bashスクリプトはコンソールの一部のルーチン操作を自動化するために使用されるため、1つのコマンドの標準出力を処理し、それを標準入力に別のコマンドに転送することが必要になる場合がありますが、1つのコマンドの実行結果は何らかの方法で処理する必要があります。 このセクションでは、スクリプト内で外部コマンドを操作する基本原則を説明します。 十分な例を挙げたと思いますが、今は要点だけを書くことができます。

1.出力を変数に渡します。

コマンドの出力を変数に書き込むには、たとえば、コマンドを引用符で囲むだけで十分です。
a = `echo "qwerty"`
echo $a

作業結果:qwerty

ただし、ディレクトリのリストを変数に書き込む場合は、結果を適切に処理してデータを変数に入れる必要があります。 小さな例を考えてみましょう:
LIST=`find /svn/ -type d 2>/dev/null| awk '{FS="/"} {print $4}'| sort|uniq | tr '\n' ' '`
for ONE_OF_LIST in $LIST
do
svnadmin hotcopy /svn/$ONE_OF_LIST /svn/temp4backup/$ONE_OF_LIST
done

ここでは、for-do-doneループを使用して、svnadmin hotcopyコマンドを使用して/ svn /フォルダー内のすべてのディレクトリをアーカイブします(この例では、例としては関係ありません)。 最も興味深いのは、次の行です: LIST=`find /svn/ -type d 2>/dev/null| awk '{FS="/"} {print $4}'| sort|uniq | tr '\n' ' '` LIST=`find /svn/ -type d 2>/dev/null| awk '{FS="/"} {print $4}'| sort|uniq | tr '\n' ' '` LIST=`find /svn/ -type d 2>/dev/null| awk '{FS="/"} {print $4}'| sort|uniq | tr '\n' ' '` LIST変数には、awk、sort、uniq、trコマンドによって処理されるfindコマンドの実行が割り当てられます(これは別の記事であるため、これらのコマンドはすべて検討しません)。 LIST変数には、同じ行にある/ svn /フォルダー内のすべてのディレクトリの名前が含まれます(ループから削除するため)。

ご覧のとおり、すべてが複雑ではなく、原則を理解し、スクリプトをいくつか記述してください。 結論として、BASHとLinuxの一般的な学習をお祈りします。 いつものように批判を歓迎します。 次の記事は、おそらくsed、awkなどのプログラムの使用について説明します。

unix-admin.suに関する記事

Source: https://habr.com/ru/post/J52871/


All Articles