1. ホーム
  2. スクリプト・コラム
  3. リナックスシェル

シェルプロセスコントロール入門

2022-02-09 10:49:54

JavaやPHPなどと違い、shのプロセスコントロールは、(以下はPHPのプロセスコントロールの書き方です)のように、空にはできません。

<span style="font-size:18px;">#include<windows.h>
#include<gl/gl.h>
#include<gl/glut.h>


// default view: at the origin in the negative direction of the z-axis

void SetupRC(void)
{
	//set the window background color to white
	glClearColor(1.0f, 1.0f, 1.0f,1.0f);
}

//Draw triangle
void DrawTriangle(void)
{
	glBegin(GL_TRIANGLES);
	glVertex2f(0.0f,0.0f);
	glVertex2f(40.0f,0.0f);
	glVertex2f(20.0f,40.0f);
	glEnd();
}

void ChangeSize(int w,int h)
{
	if (h == 0)
		h = 1;
	glViewport(0,0,w,h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	// Set the crop space
	if (w <= h)
		glOrtho(-100.0f, 100.0f, -100.0f*h/w, 100.0f*h/w, -100.0f, 100.0f);
	else
		glOrtho(-100.0f*w/h, 100.0f*w/h, -100.0f, 100.0f, -100.0f, 100.0f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void RenderScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT);


	// Set the current operation matrix to the model view matrix and reset it to the unit matrix
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	//draw the black axes
	glColor3f(0.0f,0.0f,0.0f);
	glBegin(GL_LINES);
	glVertex2f(-100.0f,0.0f);
	glVertex2f(100.0f,0.0f);
	glVertex2f(0.0f, -100.0f);
	glVertex2f(0.0f, 100.0f);
	glEnd();
	
	// Draw the first red triangle
	glColor3f(1.0f,0.0f,0.0f);
	DrawTriangle();

	//draw a green triangle rotated counterclockwise by 200 degrees

	glRotatef(200.0f,0.0f,0.0f,1.0f);
	glColor3f(0.0f,1.0f,0.0f);
	DrawTriangle();

	//This step is critical, because OpenGL effects accumulate and must return to the origin
	glLoadIdentity(); 
   

	//draw a yellow triangle with a negative inverse translation of 60 units along the x-axis
	glTranslatef(-60.0f,0.0f,0.0f);
	glColor3f(1.0f,1.0f,0.0f);
	DrawTriangle();


	//glLoadIdentity();
	glTranslatef(120.0f,0.0f,0.0f); //translate 120 in the positive direction of the x-axis
	glScalef(1.0f,2.0f,100.0f);
	glColor3f(0.0f,0.0f,1.0f);
	DrawTriangle();



	//swap the pointers of the two buffers
	//function: prevent screen flicker during complex drawing
	glutSwapBuffers();

}

int main(int argc,char *argv[])
{
	//glutInit is used to initialize the GLUT library
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
	glutCreateWindow("TransformationExample");

	glutDisplayFunc(RenderScene);
	glutReshapeFunc(ChangeSize);


	SetupRC();
	glutMainLoop();
	return 0;
}
</span>

sh/bashでは書けません。elseブランチに実行する文がない場合は、このelseを書かないようにしましょう。

もし

もし

if文の構文形式。

void glTranslated(GLdouble x,GLdouble y,GLdouble z);
void glTranslatef( GLfloat x,GLfloat y,GLfloat z);



一行で書く(端末のコマンドプロンプト用)。

void glRotated(GLdouble angle,GLdouble x,GLdouble y,GLdouble z);
void glRotatef( GLfloat angle, GLfloat x,GLfloat y,GLfloat z);

最後のfiはifのスペルを逆にしたもので、後ほど似たようなものに出会うと思います。

さもなくば

if else構文フォーマット。

void glScaled(GLdouble x,GLdouble y,GLdouble z);
void glScalef( GLfloat x,GLfloat y,GLfloat z);

if else-if else

if else-if else構文フォーマットです。

if condition1
then
 command1
elif condition2 
then 
 command2
else
 commandN
fi

次の例では、2つの変数が等しいかどうかを判断しています。

a=10
b=20
if [ $a == $b ]
then
 echo "a equals b"
elif [ $a -gt $b ]
then
 echo "a is greater than b"
elif [ $a -lt $b ]
then
 echo "a is less than b"
else
 echo "No matched conditions"
fi

出力結果です。

a は b よりも小さい

if else文は、以下のようにtestコマンドと組み合わせて使われることが多い。

num1=$[2*3]
num2=$[1+5]
if test $[num1] -eq $[num2]
then
 echo 'Two numbers are equal!'
else
 echo 'Two numbers are not equal!'
fi

出力結果です。

2つの数値は等しい!

ループ用

他のプログラミング言語と同様、Shellはforループをサポートしています。

forループの一般的な書式は以下の通りです。

for var in item1 item2 ... itemN
do
 command1
 command2
 ...
 commandN
done

線として書かれる。

for var in item1 item2 ... itemN; do command1; command2... done;

変数値がリストの中にあるとき、forループは変数名を使ってすべてのコマンドを一度だけ実行し、リストの中の現在の値を取得します。コマンドには、有効なシェルコマンドとステートメントを使用できます。リストには、置換、文字列、およびファイル名を含めることができます。

in リストはオプションです。in リストが使用されない場合、for ループはコマンドライン位置の引数を使用します。

例えば、現在のリストにある数字を順次出力する場合。

for loop in 1 2 3 4 5
do
 echo "The value is: $loop"
done

出力結果です。

値は、1
値: 2
値です。3
値です。4
値です。5

文字列の中の文字を順番に出力します。

for str in 'This is a string'
do
 echo $str
done

出力結果です。

これは文字列

whileステートメント

whileループは、一連のコマンドを実行し続け、また入力ファイルからデータを読み取るために使用されます。コマンドは通常、テスト条件です。その形式は

while condition
do
 command
done

intが0から始まり、ループが処理されるたびにintが1ずつ加算されます。上のスクリプトを実行すると、1から5までの数字が返され、終了します。

#! /bin/bash
int=1
while(( $int<=5 ))
do
 echo $int
 let "int++"
done

スクリプトを実行し、出力します。

1
2
3
4
5

上記の例では、Bashのletコマンドを使用しています。これは、変数の計算に$を追加することなく、1つまたは複数の式を実行するために使用されます。

whileループは、キーボードの情報を読み取るために使用することができます。以下の例では、入力情報を変数FILMにセットし、<Ctrl-D>を押してループを終了しています。

echo 'Press <CTRL-D> to exit'
echo -n 'Enter the name of your favorite site: '
while read FILM
do
 echo "Yes! $FILM is a good site"
done

スクリプトを実行すると、次のような出力が得られます。

終了するには、<CTRL-D> を押してください。
お好きなサイト名を入力してください:Script House
はい!!(笑 Script Houseは良いサイトです。

無限ループ

無限ループの構文形式。

while :
do
 command
done

または

while true
do
 command
done

または

for (( ; ; ))

ループまで

untilループは、条件が真になるまで一連のコマンドを実行する。

untilループは、whileループとは逆の処理方法です。

一般的にはwhileループの方がuntilループより優れていますが、untilループの方が便利な場合もあります(ごくわずかですが)。

untilの構文形式です。

until condition
do
 command
done

conditionは一般に条件式で、戻り値がfalseの場合はループ内の文の実行を継続し、それ以外の場合はループをジャンプさせる。

次の例では、untilコマンドを使って、0から9までの数字を出力しています。

#! /bin/bash

a=0

until [ ! $a -lt 10 ]
do
 echo $a
 a=`expr $a + 1`
done

結果を実行します。

出力結果は

0
1
2
3
4
5
6
7
8
9

ケース

シェルのcase文は、複数選択文です。case文は、あるパターンと値をマッチングさせ、マッチングに成功した場合、マッチングしたコマンドを実行します。case文の書式は以下の通りです。

case Value in
mode1)
 command1
 command2
 ...
 commandN
 ;;
(Mode 2)
 command1
 command2
 ...
 commandN
 commandN ;;
esac

ケースは上記のように動作します。値の後にはinという単語が続き、各パターンは右括弧で終わらなければなりません。値は変数でも定数でもよい。マッチが値がパターンにマッチすることを発見した後、;;までの間のすべてのコマンドが実行を開始します。

フェッチでは、マッチした各パターンを検出します。一旦パターンにマッチすると、マッチしたパターンに対応するコマンドが実行された後、それ以上のパターンは実行されません。どのパターンにもマッチしない場合、アスタリスク * を使って値を捕捉し、それ以降のコマンドを実行します。

次のスクリプトは、1〜4の入力を促し、各パターンにマッチさせる。

echo 'Enter a number between 1 and 4:'
echo 'The number you entered is:'
read aNum
case $aNum in
 1) echo 'You have selected 1'
 ;;
 2) echo 'You have selected 2'
 ;;
 3) echo 'You selected 3'
 ;;
 4) echo 'You selected 4'
 ;;
 *) echo 'You did not enter a number between 1 and 4'
 ;;
esac

異なる内容を入力すると、異なる結果が得られます、例.

1から4までの数字を入力してください。
入力された数値は:
3
3を選択されました。

ループから飛び出す

ループ中に、終了条件に達しない場合に強制的にループを終了させる必要がある場合がありますが、シェルはこのためにbreakとcontinueという2つのコマンドを使用します。

breakコマンド

breakコマンドは、すべてのループからジャンプアウト(後続のすべてのループの実行を終了)させるコマンドです。

次の例では、ユーザーが5より大きい数字を入力するまで、スクリプトはデッドループに入ります。このループを抜け、シェルプロンプトに戻るには、breakコマンドを使用します。

#! /bin/bash
while :
do
 echo -n "Enter a number between 1 and 5:"
 read aNum
 case $aNum in
  1|2|3|4|5) echo "The number you entered is $aNum!"
  ;;
  *) echo "The number you entered is not between 1 and 5! Game over"
   break
  ;;
 esac
done

上記のコードを実行すると、次のような出力が得られます。

1から5までの数字を入力してください:3
入力された数値は3です!
1から5:7までの数字を入力してください
1~5以外の数字を入力した!?ゲームオーバー

続ける

continueコマンドはbreakコマンドと似ていますが、すべてのループから飛び出すのではなく、現在のループから飛び出すという点が異なります。

上の例の修正版です。

#! /bin/bash
while :
do
 echo -n "Enter a number between 1 and 5: "
 read aNum
 case $aNum in
  1|2|3|4|5) echo "The number you entered is $aNum!"
  ;;
  *) echo "The number you entered is not between 1 and 5! "
   continue
   echo "Game over"
  ;;
 esac
done

コードを実行すると、この例のループは5より大きい数字が入力されても終了せず、echo "ゲームオーバー"という文が実行されないことがわかります。

場合...esac

case ... esacは、他の言語のswitch ... case文に似ている。他の言語のcase文は、複数枝の選択構造で、各case枝は右括弧で始まり、2つのセミコロン ;; で区切る。つまり、実行終了は、case ... esac文全体から飛び出して、esac(これは大文字と小文字を反転している)を終了マーカとしているのだ。

case ... esacの構文は以下のような形式です。

case value in
mode1)
 command1
 command2
 command3
 ;;
(Mode 2)
 command1
 command2
 command3
 ;;
*)
 command1
 command2
 command3
 command3;;
esac

ケースに続いて、変数や定数などの値を指定します。

値の後にはキーワードinが続き、その後にマッチする様々なパターンが続く。各パターンは右括弧で終わらなければならず、パターンは正規表現をサポートしている。

#! /bin/sh

site="jb51"

case "$site" in
 "jb51") echo "Script House"
 ;;
 "google") echo "Google search"
 ;;
 "taobao") echo "taobao"
 ;;
esac

出力は

スクリプトハウス

以上、シェルプロセス制御の詳細ですが、シェルプロセス制御の詳細については、Scripting Homeの他の関連記事にもご注目ください!