関数にブールフラグを渡しますか?

関数にブールフラグを渡しますか?

関数が変更するパラメータによって異なります。
私は私ができることを知っています:

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互換製品を作成することは困難です。

関連情報