GNU/Linux >> Linux の 問題 >  >> Linux

Bashでプログラミングする方法:構文とツール

シェルは、オペレーティングシステムのコマンドインタープリターです。 Bashは私のお気に入りのシェルですが、すべてのLinuxシェルは、ユーザーまたはsysadminによって入力されたコマンドをオペレーティングシステムが使用できる形式に解釈します。結果がシェルプログラムに返されると、STDOUTに送信され、デフォルトでターミナルに表示されます。私がよく知っているシェルはすべてプログラミング言語でもあります。

タブ補完、コマンドラインの呼び出しと編集、エイリアスなどのショートカットなどの機能はすべて、強力なシェルとしての価値に貢献しています。デフォルトのコマンドライン編集モードはEmacsを使用しますが、私のお気に入りのBash機能の1つは、Viモードに変更して、すでに筋肉の記憶の一部である編集コマンドを使用できることです。

ただし、Bashをシェルとしてのみ考えると、その真の力の多くを見逃してしまいます。 3巻のLinux自習コース(このシリーズの記事の基になっている)を研究している間、私はLinuxでの20年以上の作業で知らなかったBashについてのことを学びました。これらの新しい知識のいくつかは、プログラミング言語としての使用に関連しています。 Bashは強力なプログラミング言語であり、コマンドラインやシェルスクリプトで使用するために完全に設計されています。

この3部構成のシリーズでは、Bashをコマンドラインインターフェイス(CLI)プログラミング言語として使用する方法について説明します。この最初の記事では、Bash、変数、および制御演算子を使用した簡単なコマンドラインプログラミングについて説明します。他の記事では、Bashファイルの種類について説明しています。実行フロー制御ロジックを提供する文字列、数値、およびその他の論理演算子。さまざまなタイプのシェル拡張。およびforながら 、およびまで 反復操作を可能にするループ。また、これらのツールの使用を簡素化およびサポートするいくつかのコマンドについても説明します。

シェル

シェルは、オペレーティングシステムのコマンドインタープリターです。 Bashは私のお気に入りのシェルですが、すべてのLinuxシェルは、ユーザーまたはsysadminによって入力されたコマンドをオペレーティングシステムが使用できる形式に解釈します。結果がシェルプログラムに返されると、ターミナルに表示されます。私がよく知っているシェルはすべてプログラミング言語でもあります。

Bashシェルは、1977年にSteven Bourneによって作成された古いBourneシェルに基づいているため、Bourne Again Shellの略です。他の多くのシェルが利用可能ですが、これらは私が最も頻繁に遭遇する4つです:

  • csh: C言語の構文が好きなプログラマーのためのCシェル
  • ksh: David Kornによって作成され、Unixユーザーに人気のあるKornシェル
  • tcsh: より使いやすい機能を備えたcshのバージョン
  • zsh: 他の人気のあるシェルの多くの機能を組み合わせたZシェル

すべてのシェルには、コアユーティリティによって提供されるコマンドを補足または置換する組み込みコマンドがあります。シェルのマニュアルページを開き、「BUILT-INS」セクションを見つけて、シェルが提供するコマンドを確認します。

各シェルには、独自の個性と構文があります。いくつかは他のものよりあなたのためにうまくいくでしょう。私はCシェル、Kornシェル、およびZシェルを使用しました。私はまだそれらのどれよりもBashシェルが好きです。自分に最適なものを使用してください。ただし、他のいくつかを試す必要がある場合があります。幸い、シェルの変更は非常に簡単です。

これらのシェルはすべてプログラミング言語であり、コマンドインタープリターでもあります。これは、Bashの不可欠な部分であるいくつかのプログラミング構造とツールのクイックツアーです。

プログラミング言語としてのBash

ほとんどのシステム管理者は、Bashを使用して、通常はかなり単純で単純なコマンドを発行しています。しかし、Bashは単一のコマンドを入力するだけでなく、多くのシステム管理者が一連のタスクを実行するための単純なコマンドラインプログラムを作成します。これらのプログラムは、時間と労力を節約できる一般的なツールです。

CLIプログラムを作成するときの私の目的は、時間と労力を節約することです(つまり、怠惰なシステム管理者になることです)。 CLIプログラムは、次々に実行される特定の順序でいくつかのコマンドを一覧表示することでこれをサポートします。したがって、1つのコマンドの進行状況を監視し、最初のコマンドが終了したときに次のコマンドを入力する必要はありません。他のことをすることができ、各コマンドの進行状況を継続的に監視する必要はありません。

「プログラム」とは何ですか?

Free Online Dictionary of Computing(FOLDOC)は、プログラムを次のように定義しています。「コンピューターが実行する物理デバイスではなく、コンピューターによって実行される命令」。プリンストン大学のWordNetは、プログラムを次のように定義しています。「…コンピューターが解釈して実行できる一連の命令…」Wikipediaには、コンピュータープログラムに関する優れたエントリもあります。

したがって、プログラムは、特定の関連タスクを実行する1つ以上の命令で構成できます。コンピュータプログラム命令は、プログラムステートメントとも呼ばれます。システム管理者の場合、プログラムは通常、一連のシェルコマンドです。 Linuxで利用可能なすべてのシェル、少なくとも私が精通しているシェルには、少なくとも基本的な形式のプログラミング機能があり、ほとんどのLinuxディストリビューションのデフォルトシェルであるBashも例外ではありません。

このシリーズではBashを使用していますが(非常に普及しているため)、別のシェルを使用する場合、構成と構文は多少異なる場合がありますが、一般的なプログラミングの概念は同じです。一部のシェルは、他のシェルがサポートしていない一部の機能をサポートしている場合がありますが、それらはすべて、いくつかのプログラミング機能を提供します。シェルプログラムは、繰り返し使用するためにファイルに保存することも、必要に応じてコマンドラインで作成することもできます。

シンプルなCLIプログラム

最も単純なコマンドラインプログラムは、 Enter の前にコマンドラインで入力される、関連するかどうかに関係なく、1つまたは2つの連続するプログラムステートメントです。 キーが押されました。プログラムの2番目のステートメントがある場合は、最初のステートメントのアクションに依存している可能性がありますが、そうである必要はありません。

明確に述べる必要のある構文上の句読点も1ビットあります。コマンドラインで単一のコマンドを入力する場合は、 Enterを押します。 キーは、暗黙のセミコロン(; )でコマンドを終了します )。コマンドラインで1行として入力されたCLIシェルプログラムで使用する場合は、セミコロンを使用して各ステートメントを終了し、次のステートメントから分離する必要があります。 CLIシェルプログラムの最後のステートメントでは、明示的または暗黙的なセミコロンを使用できます。

いくつかの基本的な構文

次の例で、この構文を明確にします。このプログラムは、明示的なターミネータを備えた単一のコマンドで構成されています:

[student@studentvm1 ~]$ echo "Hello world." ;
Hello world.

それはあまりプログラムのようには思えないかもしれませんが、私が学ぶすべての新しいプログラミング言語で私が遭遇する最初のプログラムです。構文は言語ごとに少し異なる場合がありますが、結果は同じです。

この些細な、しかしユビキタスなプログラムを少し拡張してみましょう。他の実験を行ったため、結果は私のものとは異なりますが、GUIデスクトップからアカウントに初めてログインしたときに、アカウントのホームディレクトリに作成されるデフォルトのディレクトリとファイルしかない場合があります。

[student@studentvm1 ~]$ echo "My home directory." ; ls ;
My home directory.
chapter25   TestFile1.Linux  dmesg2.txt  Downloads  newfile.txt  softlink1  testdir6
chapter26   TestFile1.mac    dmesg3.txt  file005    Pictures     Templates  testdir
TestFile1      Desktop       dmesg.txt   link3      Public       testdir    Videos
TestFile1.dos  dmesg1.txt    Documents   Music      random.txt   testdir1

それはもう少し理にかなっています。結果は関連していますが、個々のプログラムステートメントは互いに独立しています。コードが少し読みやすくなるため、セミコロンの前後にスペースを入れるのが好きであることに注意してください。最後に明示的なセミコロンを付けずに、その小さなCLIプログラムを再試行してください:

[student@studentvm1 ~]$ echo "My home directory." ; ls 

出力に違いはありません。

変数に関する何か

すべてのプログラミング言語と同様に、Bashシェルは変数を処理できます。変数は、ある種の値を含むメモリ内の特定の場所を参照する記号名です。変数の値は変更可能です。つまり、変数です。

Bashは、Cや関連言語のような変数を型付けせず、整数、浮動小数点、または文字列型として定義します。 Bashでは、すべての変数は文字列です。整数である文字列は、Bashが実行できる唯一のタイプの数学である整数演算で使用できます。より複雑な計算が必要な場合は、 bc コマンドはCLIプログラムおよびスクリプトで使用できます。

変数には値が割り当てられ、CLIプログラムおよびスクリプトでそれらの値を参照するために使用できます。変数の値はその名前を使用して設定されますが、前に $はありません サイン。割り当てVAR=10 変数VARの値を10に設定します。変数の値を出力するには、ステートメント echo $ VARを使用できます。 。テキスト(つまり、数値以外の)変数から始めます。

Bash変数は、設定が解除されるまでシェル環境の一部になります。

割り当てられていない変数の初期値を確認してください。 nullである必要があります。次に、変数に値を割り当て、それを出力してその値を確認します。これらすべてを単一のCLIプログラムで実行できます:

[student@studentvm1 ~]$ echo $MyVar ; MyVar="Hello World" ; echo $MyVar ;

Hello World
[student@studentvm1 ~]$

注:変数代入の構文は非常に厳密です。等しい( =)の両側にスペースがあってはなりません )割り当てステートメントにサインインします。

空の行は、 MyVarの初期値を示しています 無効である。変数の値の変更と設定は同じ方法で行われます。この例は、元の値と新しい値の両方を示しています。

前述のように、Bashは整数算術計算を実行できます。これは、配列内の要素の位置への参照を計算したり、単純な数学の問題を実行したりする場合に役立ちます。科学計算や、財務計算などの小数が必要なものには適していません。これらのタイプの計算には、はるかに優れたツールがあります。

簡単な計算は次のとおりです。

[student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var1*Var2))"
Result = 63

浮動小数点数になる数学演算を実行するとどうなりますか?

[student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var1/Var2))"
Result = 0
[student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var2/Var1))"
Result = 1
[student@studentvm1 ~]$

結果は最も近い整数です。計算はエコーの一部として実行されたことに注意してください 声明。計算は、Bashの優先順位により、echoコマンドを囲む前に実行されます。詳細については、Bashのmanページを参照し、「precedence」を検索してください。

制御演算子

シェル制御演算子は、いくつかの興味深いコマンドラインプログラムを簡単に作成するための構文演算子の1つです。 CLIプログラムの最も単純な形式は、コマンドラインでいくつかのコマンドを順番に並べるだけです。

command1 ; command2 ; command3 ; command4 ; . . . ; etc. ;

エラーが発生しない限り、これらのコマンドはすべて問題なく実行されます。しかし、エラーが発生するとどうなりますか?組み込みの&&を使用して、エラーを予測して許容できます。 および|| Bash制御演算子。これらの2つの制御演算子は、フロー制御を提供し、コード実行のシーケンスを変更できるようにします。セミコロンも、改行文字と同様に、Bash制御演算子と見なされます。

&& オペレーターは、「command1が成功した場合は、command2を実行します。何らかの理由でcommand1が失敗した場合、command2はスキップされます」と単純に言います。その構文は次のようになります:

command1 && command2

次に、新しいディレクトリを作成し、成功した場合はそれを現在の作業ディレクトリ(PWD)にするコマンドをいくつか見てみましょう。ホームディレクトリを確認します( )は障害者です。これを最初に/rootで試してください 、アクセスできないディレクトリ:

[student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir/ && cd $Dir
mkdir: cannot create directory '/root/testdir/': Permission denied
[student@studentvm1 ~]$

エラーはmkdirによって発行されました 指図。ディレクトリの作成に失敗したため、ファイルを作成できなかったことを示すエラーは表示されませんでした。 && 制御オペレーターがゼロ以外の戻りコードを検出したため、タッチ コマンドがスキップされました。 &&を使用する コントロールオペレーターはタッチを防ぎます ディレクトリの作成中にエラーが発生したため、コマンドの実行を停止しました。このタイプのコマンドラインプログラムフロー制御は、エラーが複雑になり、実際に混乱するのを防ぐことができます。しかし、もう少し複雑にする時が来ました。

|| 制御演算子を使用すると、最初のプログラムステートメントがゼロより大きいコードを返したときに実行される別のプログラムステートメントを追加できます。基本的な構文は次のようになります:

command1 || command2 

この構文は、「command1が失敗した場合は、command2を実行します」と読みます。これは、command1が成功した場合、command2がスキップされることを意味します。新しいディレクトリを作成してみてください:

[student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir || echo "$Dir was not created."
mkdir: cannot create directory '/root/testdir': Permission denied
/root/testdir was not created.
[student@studentvm1 ~]$

これはまさにあなたが期待することです。新しいディレクトリを作成できなかったため、最初のコマンドが失敗し、2番目のコマンドが実行されました。

これらの2つの演算子を組み合わせると、両方の長所が得られます。フロー制御を使用する制御演算子の構文は、 &&の場合、この一般的な形式を取ります。 および|| 制御演算子が使用されます:

preceding commands ; command1 && command2 || command3 ; following commands

この構文は次のように記述できます。「command1が戻りコード0で終了する場合は、command2を実行し、それ以外の場合はcommand3を実行します。」試してみてください:

[student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
mkdir: cannot create directory '/root/testdir': Permission denied
/root/testdir was not created.
[student@studentvm1 ~]$

ここで、 / root の代わりにホームディレクトリを使用して、最後のコマンドを再試行します ディレクトリ。このディレクトリを作成する権限があります:

[student@studentvm1 ~]$ Dir=~/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
[student@studentvm1 testdir]$

command1 &&command2のような制御演算子の構文 は、すべてのコマンドが正常に完了したかどうか、または実行中に何らかの障害が発生したかどうかを示すリターンコード(RC)をシェルに送信するために機能します。慣例により、ゼロ(0)のRCは成功を示し、正の数はある種の失敗を示します。 sysadminsが使用するツールの中には、障害を示すために1つだけを返すものもありますが、多くのツールは、発生した障害のタイプを示すために他のコードを使用します。

Bashシェル変数$? 最後のコマンドのRCが含まれています。このRCは、スクリプト、コマンドリスト内の次のコマンド、またはsysadminによって直接チェックできます。簡単なコマンドを実行し、すぐにRCを確認することから始めます。 RCは常に、それを見る前に実行された最後のコマンド用です。

[student@studentvm1 testdir]$ ll ; echo "RC = $?"
total 1264
drwxrwxr-x  2 student student   4096 Mar  2 08:21 chapter25
drwxrwxr-x  2 student student   4096 Mar 21 15:27 chapter26
-rwxr-xr-x  1 student student     92 Mar 20 15:53 TestFile1
<snip>
drwxrwxr-x. 2 student student 663552 Feb 21 14:12 testdir
drwxr-xr-x. 2 student student   4096 Dec 22 13:15 Videos
RC = 0
[student@studentvm1 testdir]$

この場合、RCはゼロです。これは、コマンドが正常に完了したことを意味します。次に、rootのホームディレクトリ(権限のないディレクトリ)で同じコマンドを試してください。

[student@studentvm1 testdir]$ ll /root ; echo "RC = $?"
ls: cannot open directory '/root': Permission denied
RC = 2
[student@studentvm1 testdir]$

この場合、RCは2つです。これは、root以外のユーザーが、アクセスが許可されていないディレクトリにアクセスするための許可が拒否されたことを意味します。制御オペレーターはこれらのRCを使用して、プログラムの実行順序を変更できるようにします。

概要

この記事では、Bashをプログラミング言語と見なし、その基本的な構文といくつかの基本的なツールについて説明しました。データをSTDOUTに出力する方法と、変数と制御演算子を使用する方法を示しました。このシリーズの次の記事では、命令実行のフローを制御する多くのBash論理演算子のいくつかを見ていきます。


Linux
  1. pushdとpopdを使用してBashシェルをナビゲートする

  2. cronシェルを変更する方法(shからBash)?

  3. Bashスクリプトでユーザーアカウントとパスワードを自動的に追加する方法は?

  1. Linuxコマンドラインツールを使用してJSONを解析してきれいに印刷する方法

  2. .bashrcの目的とそれはどのように機能しますか?

  3. Bashシェルスクリプトで文字列を比較する方法

  1. 方法:無制限の Bash/シェル履歴?

  2. Bashでwatchコマンドとjobsコマンドを一緒に使用するにはどうすればよいですか?

  3. bash シェルでファイルのセクションを grep する方法