関数が変更するパラメータによって異なります。
私は私ができることを知っています:
function foo {
PARAM1=$1
PARAM2="$2"
VAR=$3
if[[ -z "$VAR" ]]; then
# code here
else
# other code here
fi
}
Bashにもっと適切な方法があるかどうか疑問に思います。これはうまくいきますが、私は次のようなものを望んでいません
foo "x" "y" "blah"
foo "x" "y" "true"
foo "y" "y" "1"
すべてが同じです。
Bashを使用するより良い方法はありますか?
答え1
関数にコマンドラインオプションを提供できます。引数なしでコマンドラインオプションを使用することは、シェルスクリプト、シェル関数、およびユーティリティにバイナリ/ブール値(「on / off」、「true / false」、「enable / disable」)を提供する一般的な方法です。
foo () {
local flag=false
OPTIND=1
while getopts 't' opt; do
case $opt in
t) flag=true ;;
*) echo 'Error in command line parsing' >&2
exit 1
esac
done
shift "$(( OPTIND - 1 ))"
local param1="$1"
local param2="$2"
if "$flag"; then
# do things for "foo -t blah blah"
else
# do things for "foo blah blah"
fi
}
このオプションは-t
ユーザーにブールフラグとして表示されます。これを使用すると、flag
関数は内部的にtrue
(デフォルトをに変更false
)に設定されます。この-t
オプションは関数の最初のパラメータとして使用されます。
この関数を呼び出すには、次を使用できます。
foo "some value" "some other value"
または
foo -t "some value" "some other value"
後者の呼び出しはflag
関数の変数をに設定しますtrue
。
答え2
一般的に言えば
通常、ブール値を関数に渡すことはどの言語でも読み取ることができません。たとえばcalculate_interest 5y 4% true
。読者は何が本当であるか疑問になります。
従って列挙型を使用して下さい: { per_month, per_year }
。今、あなたはそれを行うことができますcalculate_interest 5y 4% per_year
。これはもっと読みやすいです。
バッシュから
Bashは静的に型指定されていないため(または強力な型があるか、型システムがまったくありません)、さまざまな値を渡すことができます。ある人はこの道を選び、他の人はそうではありません。私たちは同じ道をたどる様々な価値を望んでいません。
したがって、入力が許可されている2つの値のいずれかであることを確認するコードを追加してください。関数の先頭にこれを行います。作業を終えた後、1/2を終了したくありません。
ブール値を使用する関数を呼び出す必要がある場合の対処
誰かが私のアドバイスに従わなかったので、ブール値を使用して関数を呼び出す必要があります。コードを読みやすくするために何ができますか?
- 言語(Pythonなど)で名前付きパラメータ(たとえば)を許可する場合は、そのパラメータ
calculate_interest 5y 4% per_year=True
を使用してください。役に立ちますが、意味を教えてくれませんcalculate_interest 5y 4% per_year=False
。 - 言語に名前付きパラメータがない場合、唯一のオプションは、読み取れないコード(オプションではない)を受け入れるか、関数を読み書き機能でラップすることです。
答え3
次の形式に従うことをお勧めします。
foo() {
# Limit scope of variables
local 'opt1' 'opt2' 'opt3' 'operands'
# Default values
opt1='default1'
opt2='default2'
opt3='false'
operands=()
# Arguments handling
while (( ${#} > 0 )); do
case "${1}" in
( '--opt1='* ) opt1="${1#*=}" ;; # Handles --opt1
( '--opt2='* ) opt2="${1#*=}" ;; # Handles --opt2
( '--opt3='* ) opt3="${1#*=}" ;; # Handles --opt3
( '--' ) operands+=( "${@:2}" ); break ;; # End of options
( '-'?* ) ;; # Discard non-valid options
( * ) operands+=( "${1}" ) # Handles operands
esac
shift
done
...
}
これにより、関数がより強力になり、読みやすくなります。
$ foo
Options:
opt1: [default1]
opt2: [default2]
opt3: [false]
$ foo --opt1='value1' --opt2='value2' --opt3='true' 'foo' 'bar' 'baz'
Options:
opt1: [value1]
opt2: [value2]
opt3: [true]
Operands:
1: [foo]
2: [bar]
3: [baz]
利点:
- 読みやすく理解しやすいです。
- 構文は一般的なコマンドラインユーティリティと似ています。
- 互換性を維持しながら、より多くのオプションを簡単に追加できます。
欠点:
- 小さくてシンプルなスクリプトは過剰になることがあります。
- 長いオプションとオペランドを処理するために移植可能でPOSIX互換製品を作成することは困難です。