BASHプログラミング
 Computer >> コンピューター >  >> プログラミング >> BASHプログラミング

Bashでプログラミングする方法:ループ

Bashは強力なプログラミング言語であり、コマンドラインやシェルスクリプトで使用するために完全に設計されています。この3部構成のシリーズは、私の3巻のLinux自習コースに基づいており、コマンドラインインターフェイス(CLI)でプログラミング言語としてBashを使用する方法を探っています。

このシリーズの最初の記事では、変数や制御演算子の使用など、Bashを使用した簡単なコマンドラインプログラミングについて説明しました。 2番目の記事では、Bashで実行フロー制御ロジックとさまざまなタイプのシェル拡張を提供するファイル、文字列、数値、およびその他の論理演算子のタイプについて説明しました。この3番目(そして最後)の記事では、さまざまなタイプの反復操作を実行するためのループの使用と、それらのループを制御する方法について説明します。

ループ

私が今まで使用したすべてのプログラミング言語には、反復操作を実行するためのさまざまな機能を提供する少なくとも2種類のループ構造があります。私はforループを頻繁に使用しますが、whileループとuntilループも便利です。

forループ

Bashによるforの実装 私の意見では、コマンドは数値以外の値を処理できるため、ほとんどのコマンドよりも少し柔軟性があります。対照的に、たとえば、 forの標準C言語 ループは数値のみを処理できます。

forのBashバージョンの基本構造 コマンドは簡単です:

list1のVarの
for Var in list1 ; do list2 ; done

これは次のように解釈されます。「list1の値ごとに、 $ Varを設定します。 その値に変更し、その値を使用してlist2のプログラムステートメントを実行します。 list1のすべての値が使用されると、終了するため、ループを終了します。」list1の値は、単純で明示的な値の文字列にすることも、コマンド置換の結果にすることもできます(2番目の説明で説明します)。シリーズの記事)。私はこの構成を頻繁に使用します。

試してみるには、〜/ testdirであることを確認してください は現在の作業ディレクトリ(PWD)です。ディレクトリをクリーンアップしてから、 forの簡単な例を見てください。 値の明示的なリストから始まるループ。このリストは英数字の値を組み合わせたものですが、すべての変数が文字列であり、そのように扱うことができることを忘れないでください。

[student@studentvm1 testdir]$ rm *
[student@studentvm1 testdir]$ for I in a b c d 1 2 3 4 ; do echo $I ; done
a
b
c
d
1
2
3
4

これは、より意味のある変数名を持つもう少し便利なバージョンです:

[student@studentvm1 testdir]$ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Department $Dept" ; done 
Department Human Resources
Department Sales
Department Finance
Department Information Technology
Department Engineering
Department Administration
Department Research

いくつかのディレクトリを作成します(そして、そうしている間、いくつかの進捗情報を表示します):

[student@studentvm1 testdir]$ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Working on Department $Dept" ; mkdir "$Dept"  ; done 
Working on Department Human Resources
Working on Department Sales
Working on Department Finance
Working on Department Information Technology
Working on Department Engineering
Working on Department Administration
Working on Department Research
[student@studentvm1 testdir]$ ll
total 28
drwxrwxr-x 2 student student 4096 Apr  8 15:45  Administration
drwxrwxr-x 2 student student 4096 Apr  8 15:45  Engineering
drwxrwxr-x 2 student student 4096 Apr  8 15:45  Finance
drwxrwxr-x 2 student student 4096 Apr  8 15:45 'Human Resources'
drwxrwxr-x 2 student student 4096 Apr  8 15:45 'Information Technology'
drwxrwxr-x 2 student student 4096 Apr  8 15:45  Research
drwxrwxr-x 2 student student 4096 Apr  8 15:45  Sales

$ Dept 変数は、 mkdirで引用符で囲む必要があります 声明;それ以外の場合、2つの部分からなる部門名(「情報技術」など)は、2つの別個の部門として扱われます。これは、私が従うのが好きなベストプラクティスを強調しています。すべてのファイル名とディレクトリ名は1つの単語である必要があります。最新のオペレーティングシステムのほとんどは名前のスペースを処理できますが、これらの特殊なケースがスクリプトやCLIプログラムで考慮されるようにするには、システム管理者が余分な作業を行う必要があります。 (どのファイルを使用するかわからないために煩わしい場合でも、ほぼ確実に検討する必要があります。)

したがって、〜/ testdir内のすべてを削除します —もう一度—そしてこれをもう一度行います:

[student@studentvm1 testdir]$ rm -rf * ; ll
total 0
[student@studentvm1 testdir]$ for Dept in Human-Resources Sales Finance Information-Technology Engineering Administration Research ; do echo "Working on Department $Dept" ; mkdir "$Dept"  ; done
Working on Department Human-Resources
Working on Department Sales
Working on Department Finance
Working on Department Information-Technology
Working on Department Engineering
Working on Department Administration
Working on Department Research
[student@studentvm1 testdir]$ ll
total 28
drwxrwxr-x 2 student student 4096 Apr  8 15:52 Administration
drwxrwxr-x 2 student student 4096 Apr  8 15:52 Engineering
drwxrwxr-x 2 student student 4096 Apr  8 15:52 Finance
drwxrwxr-x 2 student student 4096 Apr  8 15:52 Human-Resources
drwxrwxr-x 2 student student 4096 Apr  8 15:52 Information-Technology
drwxrwxr-x 2 student student 4096 Apr  8 15:52 Research
drwxrwxr-x 2 student student 4096 Apr  8 15:52 Sales

誰かが特定のLinuxコンピューター上のすべてのRPMのリストとそれぞれの簡単な説明を求めたとします。私がノースカロライナ州で働いていたとき、これは私に起こりました。当時、オープンソースは州の機関による使用が「承認」されておらず、デスクトップコンピューターでLinuxのみを使用していたため、先のとがった髪のボス(PHB)は、コンピューターにインストールされている各ソフトウェアのリストを必要としていました。例外を「承認」できること。

どのようにアプローチしますか? rpm –qa という知識から始める1つの方法があります コマンドは、PHBが必要とする2つの項目(ソフトウェア名と簡単な要約)を含む、RPMの完全な説明を提供します。

一度に1ステップずつ最終結果を作成します。まず、すべてのRPMを一覧表示します:

[student@studentvm1 testdir]$ rpm -qa 
perl-HTTP-Message-6.18-3.fc29.noarch
perl-IO-1.39-427.fc29.x86_64
perl-Math-Complex-1.59-429.fc29.noarch
lua-5.3.5-2.fc29.x86_64
java-11-openjdk-headless-11.0.ea.28-2.fc29.x86_64
util-linux-2.32.1-1.fc29.x86_64
libreport-fedora-2.9.7-1.fc29.x86_64
rpcbind-1.2.5-0.fc29.x86_64
libsss_sudo-2.0.0-5.fc29.x86_64
libfontenc-1.1.3-9.fc29.x86_64
<snip>

並べ替えを追加します およびuniq リストを並べ替えて一意のリストを印刷するコマンド(同じ名前のRPMがインストールされている可能性があるため):

[student@studentvm1 testdir]$ rpm -qa | sort | uniq
a2ps-4.14-39.fc29.x86_64
aajohan-comfortaa-fonts-3.001-3.fc29.noarch
abattis-cantarell-fonts-0.111-1.fc29.noarch
abiword-3.0.2-13.fc29.x86_64
abrt-2.11.0-1.fc29.x86_64
abrt-addon-ccpp-2.11.0-1.fc29.x86_64
abrt-addon-coredump-helper-2.11.0-1.fc29.x86_64
abrt-addon-kerneloops-2.11.0-1.fc29.x86_64
abrt-addon-pstoreoops-2.11.0-1.fc29.x86_64
abrt-addon-vmcore-2.11.0-1.fc29.x86_64
<snip>

これにより、確認したいRPMの正しいリストが得られるため、これをループへの入力リストとして使用して、各RPMのすべての詳細を出力できます。

[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done

このコードは、必要以上のデータを生成します。ループが完了していることに注意してください。次のステップは、PHBが要求した情報のみを抽出することです。したがって、 egrepを追加します コマンド。^名前を選択するために使用されます または^概要 。カラット( ^ )行の先頭を指定します。したがって、行の先頭にNameまたはSummaryが付いている行が表示されます。

[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary"
Name        : a2ps
Summary     : Converts text and other types of files to PostScript
Name        : aajohan-comfortaa-fonts
Summary     : Modern style true type font
Name        : abattis-cantarell-fonts
Summary     : Humanist sans serif font
Name        : abiword
Summary     : Word processing program
Name        : abrt
Summary     : Automatic bug detection and reporting tool
<snip>

grepを試すことができます egrepの代わりに 上記のコマンドでは動作しませんが、動作しません。このコマンドの出力をlessにパイプすることもできます 結果を調べるためにフィルタリングします。最終的なコマンドシーケンスは次のようになります。

[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary" > RPM-summary.txt

このコマンドラインプログラムは、パイプライン、リダイレクト、および for を使用します ループ-すべて1行で。小さなCLIプログラムの出力を、電子メールで使用したり、他の目的の入力として使用したりできるファイルにリダイレクトします。

プログラムを一度に1ステップずつ構築するこのプロセスにより、各ステップの結果を確認し、期待どおりに機能し、目的の結果が得られることを確認できます。

この演習から、PHBは1,900を超える個別のRPMパッケージのリストを受け取りました。私は誰もがそのリストを読んだことを真剣に疑っています。しかし、私は彼らに彼らが求めているものを正確に伝えました、そして私は彼らからそれについて別の言葉を聞いたことがありませんでした。

その他のループ

Bashで使用できるループ構造にはさらに2つのタイプがあります。while およびまで 構文と機能の両方で互いに非常に類似している構造。これらのループ構造の基本的な構文は単純です:

while [ expression ] ; do list ; done

および

until [ expression ] ; do list ; done

最初のロジックは次のとおりです。「式がtrueと評価されている間に、プログラムステートメントのリストを実行します。式がfalseと評価されたら、ループを終了します。」そして2番目:「式がtrueと評価されるまで、プログラムステートメントのリストを実行します。式がtrueと評価されたら、ループを終了します。」

Whileループ

ながら ループは、論理式がtrueと評価されている間(限り)、一連のプログラムステートメントを実行するために使用されます。 PWDは引き続き〜/ testdirである必要があります 。

whileの最も単純な形式 ループは永遠に実行されるものです。次の形式では、trueステートメントを使用して、常に「true」の戻りコードを生成します。単純な「1」を使用することもできますが、これはまったく同じように機能しますが、これは真のステートメントの使用法を示しています。

[student@studentvm1 testdir]$ X=0 ; while [ true ] ; do echo $X ; X=$((X+1)) ; done | head
0
1
2
3
4
5
6
7
8
9
[student@studentvm1 testdir]$

このCLIプログラムは、その部分を学習したので、より意味のあるものになるはずです。まず、 $ Xを設定します 前のプログラムまたはCLIコマンドからの値が残っている場合はゼロになります。次に、論理式 [true] 常に1と評価されます。これは、実行間のプログラム命令のリストです。 および完了 永久に実行されるか、 Ctrl + Cを押すまで実行されます または、信号2をプログラムに送信します。これらの命令は、 $ Xの現在の値を出力する算術展開です。 次に、それを1つインクリメントします。

システム管理者のためのLinux哲学の信条の1つ エレガンスを追求することであり、エレガンスを実現する1つの方法はシンプルさです。変数インクリメント演算子++を使用すると、このプログラムを簡略化できます。 。最初に、変数の現在の値が出力され、次に変数がインクリメントされます。これは、 ++を配置することで示されます 変数の後の演算子:

[student@studentvm1 ~]$ X=0 ; while [ true ] ; do echo $((X++)) ; done | head
0
1
2
3
4
5
6
7
8
9

ここで|を削除します頭 プログラムの最後から実行してください。

このバージョンでは、変数はその値が出力される前にインクリメントされます。これは、 ++を配置することで指定されます 変数の前の演算子。違いがわかりますか?

[student@studentvm1 ~]$ X=0 ; while [ true ] ; do echo $((++X)) ; done | head
1
2
3
4
5
6
7
8
9

2つのステートメントを1つのステートメントに減らし、変数の値を出力してその値をインクリメントしました。デクリメント演算子-もあります 。

特定の番号でループを停止する方法が必要です。これを実現するには、真の式を実際の数値評価式に変更します。プログラムを5にループさせ、停止します。以下のサンプルコードでは、 -le 「以下」の論理数値演算子です。これは、「 $ Xである限り が5以下の場合、ループは続行されます。 $ Xの場合 6に増加すると、ループは終了します。」

[student@studentvm1 ~]$ X=0 ; while [ $X -le 5 ] ; do echo $((X++)) ; done 
0
1
2
3
4
5
[student@studentvm1 ~]$
ループするまで

まで コマンドはwhileと非常によく似ています 指図。違いは、論理式が「true」と評価されるまでループを続けることです。この構成の最も単純な形式を見てください:

[student@studentvm1 ~]$ X=0 ; until false  ; do echo $((X++)) ; done | head
0
1
2
3
4
5
6
7
8
9
[student@studentvm1 ~]$

論理比較を使用して特定の値にカウントします:

[student@studentvm1 ~]$ X=0 ; until [ $X -eq 5 ]  ; do echo $((X++)) ; done
0
1
2
3
4
[student@studentvm1 ~]$ X=0 ; until [ $X -eq 5 ]  ; do echo $((++X)) ; done
1
2
3
4
5
[student@studentvm1 ~]$
概要

このシリーズでは、Bashコマンドラインプログラムとシェルスクリプトを構築するための多くの強力なツールについて説明しました。しかし、Bashでできる多くの興味深いことの表面をかろうじて傷つけています。残りはあなた次第です。

私は、Bashプログラミングを学ぶための最良の方法はそれを行うことであることを発見しました。複数のBashコマンドを必要とする単純なプロジェクトを見つけて、それらからCLIプログラムを作成します。システム管理者はCLIプログラミングに役立つ多くのタスクを実行するため、自動化するタスクを簡単に見つけることができると確信しています。

何年も前に、他のシェル言語とPerlに精通していましたが、すべてのsysadmin自動化タスクにBashを使用することにしました。時々少し検索することで、Bashを使用して必要なすべてを実行できることを発見しました。


  1. 頼りになるコマンドライン言語としてBashをPythonに置き換える方法

    私はbashと少し愛と憎しみの関係を持っています。私はターミナルで多くの時間を過ごします、そしてbashは私のデフォルトの「プログラミング言語」です。時々私は、find、grep、xargsがインフラストラクチャを実行していることを人々に伝え、彼らは私が本気であることに気付くまで笑い、笑います。 Pythonを入手することは、システム管理者にとって最適な選択です。また、ターミナルで何かを処理する必要があるが、bashを使用したくない場合や、bashには複雑すぎるニーズがある場合にも最適です。タスクが超えたら find $(pwd) -name *.txt | xargs -I {} ech

  2. Excel で学生データベースを作成する方法 (簡単な手順)

    データベース 膨大な量のデータと情報を確実に処理できます。データをより効果的に保持するため、ワークシートでは理解できないレベルのデータが含まれています。 データベース 多くの場合、データの取得を簡単にするために作成されます。 エクセル データベースは、ワークシートの数式が情報を容易に利用できるように配置および構造化されたデータの行と列を含むワークシートです。この記事では、Excel で学生データベースを作成する手順を示します。 テンプレートをダウンロード 学生データベースのテンプレートをダウンロードして、それらを使って練習できます。 Excel で学生データベースを作成するための段階的な手