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

シェルスクリプトパートV:Bashの関数

やあ! HowToForgeのシェルスクリプトチュートリアルシリーズへようこそ。チュートリアルの以前のリリースを読みたい場合は、チュートリアルのパート1、パート2、パート3、およびパート4についてはここをクリックしてください。このパートでは、関数を作成してスクリプトを効率的に構造化する方法を学習します。このチュートリアルを終了するまでに、LinuxのBashシェルで関数を作成し、関数にパラメーターを渡し、関数からメインコードにいくつかの値を返す方法を理解できるようになります。始めましょう!

はじめに

プログラミング言語ではサブルーチンとも呼ばれる関数は、メインルーチンの特定のタスクを実行する一連の命令です[1]。これにより、プログラマーは複雑で長いコードを小さなセクションに分割し、必要なときにいつでも呼び出すことができます。各関数は、実行するためにメインルーチンによって呼び出される必要があります。したがって、関数はコードの他の部分と分離されており、コードテストの簡単な方法を作成します。さらに、関数はいつでも繰り返し呼び出すことができるため、コードを再利用、最適化、および最小化できます。ほとんどのプログラミング言語と同様に、bashシェルも関数をサポートしています。

一般的な構文:

  1. 構文1:
    function function_name
    {
        ##### set of commands
    }
  2. 構文2:
    function_name()
    {
        #### set of commands
    }
関数の作成

bashは、関数の2つの構造をサポートします。最初の構文を使用する場合は、キーワードfunctionを使用し、その後に関数名を使用し、括弧と中括弧を開いたり閉じたりして、関数の内容をメインルーチンに区切る必要があります。 PHPの関数は同じ方法で宣言されるため、PHPのバックグラウンドがある場合は、この構文に慣れているでしょう。もう1つの構文は、関数名、開き括弧と閉じ括弧、および中括弧のみで構成されます。

#!/bin/bash
myfunction(){
    echo "My function works!"
}
myfunction

この例では、2番目の構文を使用しました。関数myfunctionを作成した後、その関数名をメインルーチンに呼び出すことによって呼び出されました。メインルーチンは、関数の一部として定義されていないスクリプト内の任意の場所にあります。

次に、コードを再配置して、スクリプト内のどこでも関数を宣言できるかどうかをテストしましょう。以下のコードを検討してください:

#!/bin/bash
echo "testing my function"
myfunction

myfunction(){
    echo "My function works!"
}

上記のコードの3行目は、コマンドが見つからないというエラーを返します。これは、次のことを意味するだけです:

The function only works if it is declared before your main routine. The interpreter will return an error if you have declared your function after your main routine.
関数を使用したコードの再構築

関数の最も優れた機能の1つは、コードを再利用できることです。プロシージャでコマンドを繰り返し実行する必要があるが、ループステートメントを使用して構造化できない場合は、関数が解決策になる可能性があります。

たとえば、次のコードについて考えてみます。

#!/bin/bash
while(true)
do
    clear
    printf "Choose from the following operations: \n"
    printf "[a]ddition\n[b]Subtraction\n[c]Multiplication\n[d]Division\n"
    printf "################################\n"
    read -p "Your choice: " choice
    case $choice in
    [aA])
        read -p "Enter first integer: " int1
        read -p "Enter second integer: " int2
        res=$((int1+int2))

    ;;
    [bB])
        read -p "Enter first integer: " int1
        read -p "Enter second integer: " int2
    res=$((int1-int2))

    ;;
    [cC])
        read -p "Enter first integer: " int1
        read -p "Enter second integer: " int2
        res=$((int1*int2))

    ;;
    [dD])
        read -p "Enter first integer: " int1
        read -p "Enter second integer: " int2
        res=$((int1/int2))

    ;;
    *)
        res=0
        echo "wrong choice!"
    esac

    echo "The result is: " $res
    read -p "Do you wish to continue? [y]es or [n]o: " ans
    if [ $ans == 'n' ]
        then
         echo "Exiting the script. Have a nice day!"
        break
    else
        continue
    fi

done

スクリプトは正常に実行されていますが、入力を受け入れるための行は、switchステートメントの各パターンで繰り返し実行されていることに注意してください。

#!/bin/bash
inputs(){
     read -p "Enter first integer: " int1
    read -p "Enter second integer: " int2
}

exitPrompt(){
    read -p "Do you wish to continue? [y]es or [n]o: " ans
    if [ $ans == 'n' ]
    then
        echo "Exiting the script. Have a nice day!"
        break
    else
        continue
    fi
}

while(true)
    do
    clear
    printf "Choose from the following operations: \n"
    printf "[a]Addition\n[b]Subtraction\n[c]Multiplication\n[d]Division\n"
    printf "################################\n"
    read -p "Your choice: " choice

    case $choice in
    [aA])
        inputs
        res=$((int1+int2))
    ;;

    [bB])
        inputs
        res=$((int1-int2))
    ;;

    [cC])
        inputs
        res=$((int1*int2))
    ;;

    [dD])
        inputs
        res=$((int1/int2))
    ;;

    *)
        res=0
        echo "wrong choice!"
    esac

    echo "The result is: " $res
    exitPrompt
done

サブセクションinputsとexitPromptを作成することで、コードを改善しました。以前のコードとまったく同じように機能しますが、現在のコードは適切に構造化されているため、トラブルシューティングが簡単です。

関数にパラメーターを渡す

ほとんどのプログラミング言語と同様に、bashの関数でパラメーターを渡し、それらのデータを処理できます。以下のコードは、シェルスクリプトで値を渡す方法の手順を示しています。

#!/bin/bash
myfunction(){
    echo $1
    echo $2
}

myfunction "Hello" "World"

この例では、myfunctionを呼び出した後、値「Hello」と「World」を追加したことに注意してください。これらの値はパラメータとしてmyfunctionに渡され、ローカル変数に格納されます。ただし、他の言語とは異なり、インタープリターは渡された値を事前定義された変数に格納します。事前定義された変数は、パラメーターを渡す順序に従って名前が付けられます。1は、渡される順序までの開始名です。 「Hello」という単語が変数1に格納され、値「World」が変数2に格納されていることに注意してください。

注:この例の1と2はローカル変数であるため、パラメーターが渡される関数以外のスクリプトの他の部分にはアクセスできません。

たとえば、

#!/bin/bash
myfunction(){
    echo $1
    echo $2
}

myfunction "Hello" "World"
echo $1
echo $2

スクリプトの最後の2行にあるecho$1とecho$2は、両方ともmyfunctionに対してローカルであるため、インタープリターが両方の変数を認識しないため、表示されません。

関数から値を返す

関数を作成してパラメーターを渡す以外に、bash関数は、キーワードreturnを使用して、関数のローカル変数の値をメインルーチンに渡すことができます。戻り値は、デフォルトの変数$?に保存されます。たとえば、次のコードについて考えてみます。

#!/bin/bash
add(){
    sum=$(($1+$2))
    return $sum
}

read -p "Enter an integer: " int1
read -p "Enter an integer: " int2
add $int1 $int2
echo "The result is: " $?
>

この例では、パラメーターint1とint2をadd関数に渡します。次に、add関数はsum =$(($ 1 + $ 2))の行を介してそれを処理します。次に、sum変数の値は、行return$sumを介してメインルーチンに渡されます。デフォルトでは、$ sumの値はデフォルトの変数$?に格納されます。最後に、行echo "結果は次のとおりです:" $?結果を出力します。

Note: Shell scripts can only return a single value.

他のプログラミング言語とは異なり、シェルスクリプトは関数から複数の値を返すことはできません。この例を見てみましょう:

#!/bin/bash
add(){
    sum=$(($1+$2))
    dif=$(($1-$2))
    return $sum
}

read -p "Enter an integer: " int1
read -p "Enter an integer: " int2
add $int1 $int2
echo "The result is: " $?
echo "The result is: " $?

まとめる

関数を使用し、パラメーターを渡して値を返す別の例を見てみましょう。

#!/bin/bash
#####################
#Author: HowtoForge #
#####################

clear(){
    clear
}

bin(){
    bin1=$(echo "obase=2;$1"|bc)
    echo $bin1
}

dec(){
    dec1=$(echo "ibase=2;$1"|bc)
    return $dec1
}

########Main#########
    printf "Choose from the following operations:\n[1]Decimal to Binary Conversion\n"
    printf "[2]Binary to Decimal Conversion\n"
    read -p "Your choice: " op
    case $op in

    1)
        read -p "Enter integer number: " int
        bin $int
    ;;

    2)
        read -p "Enter binary number: " int
        dec $int
        echo "The decimal equivalent of $int is $?"
    ;;

    *)
        echo "Wrong Choice!"
    esac

与えられた例は、obaseおよびibaseコマンドを使用して、与えられた入力を2進値または10進値の両方に変換します。行$(echo "obase =2; $ 1" | bc)は、指定された10進値を2進数に変換し、それをbin1変数に格納します。次に、echoコマンドを使用して$bin1の値を表示しました。

Note: It's better to use echo directly when converting from decimal to binary because when you return command to pass a binary value, the bash converts the binary value to decimal before returning it.

さらに、コマンド$(echo "ibase =2; $ 1" | bc)を使用して2進値を10進数に変換しました。

また、インタプリタは8ビットの2進数しか受け入れることができないことを覚えておく必要があります。 8ビットの制限を超える桁を入力すると、オーバーフローが発生し、桁の最上位ビットが破棄されます。

10ビットの2進数1000001010は、8ビットの規則に従って10を返します。これは、右側の残りの2ビット(最上位ビット)が省略されるため、1000001010は00001010に等しくなり、10に等しくなります。 8ビットを超える2進数を受け入れる操作が必要な場合は、コードを手動で作成する必要があります。

結論

Bashにはプログラミング言語と非常によく似た機能があり、ユーザーに多数のツールを提供し、Linuxシステムをより強力にします。このシリーズでは、関数を使用してシェルスクリプトの知識を深めました。シェルスクリプトで機能し、ユーザーにモジュール性を提供して、スクリプトのトラブルシューティングを容易にし、コードの再利用を可能にします。


Linux
  1. Bashスクリプト(I)

  2. シェル変数の関数?

  3. Bash で関数を作成して呼び出す方法

  1. Bashシェルのカスタマイズ

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

  3. Bash初心者シリーズ#9:Bashでの関数の使用

  1. Linux Cプログラミングチュートリアルパート18:再帰関数

  2. Linux でコマンド ライン シェル関数を使用する方法

  3. シェル スクリプトで関数名のリストを取得する