POSIX正規表現は文字列の最初の出現に一致します

POSIX正規表現は文字列の最初の出現に一致します

長いオプション ("--option") のみをサポートする bash スクリプトがあります。--option には、オプションで 1 つ以上の引数を指定できます。最初の '--' またはコマンド ライン文字列の末尾まで (ただし、最初の '--' は含みません) のすべての単語 (空白で区切られたもの) は、"--option-arguments" と見なされます。結果の末尾にスペースがあっても問題ありません。この関数は、可能なオプションごとに他の関数によって呼び出されるため、最大のパフォーマンスが求められます。したがって、bash ループと外部コマンドを回避しようとします。

「初回発生」の問題に何時間も格闘し、ついにこの答えそれは、POSIX (および bash) が非貪欲/遅延正規表現演算子をサポートしていないことを思い出させました。

何をするか?

答え1

オプションは文字列ではなく、リスト文字列。、、、、が個別の引数としてmyscript --option foo bar -- qux含まれますが、いずれにも空白は含まれません。myscript--optionfoobar--qux

bash ではループが最適な方法です。

case "$1" in
  --option1)
    shift
    while [[ $# -ne 0 && "$1" != "--" ]]; do
      option1_args+=("$1")
      shift
    done
    (($# == 0)) || shift
done

パフォーマンスがそれほど問題になる場合は、bash を使用するべきではありません。代わりに ksh を試してください。これは無料で、デフォルトでインストールされていなくてもほとんどどこでも利用でき、多くの場合 bash よりも大幅に高速です。それでもまだ遅い場合は、Perl、Python、Ruby などのより高度なプログラミング言語が必要です。

答え2

かなり簡単な解決策を見つけました...

function optionArg () {
  local _find="$1"; shift 1
  local _optarg=""
  local _reBeg=""
  #
  _reBeg="${_find}"'[= ]+(.*?)( --)?'
  ### no regex nongreedy operator support in POSIX
  ### will have to just truncate after first match
  #
  if [[ "$*" =~ $_reBeg ]]
  then
    _optarg="${BASH_REMATCH[1]}"
    ### all arguments following --option[= ]
    #
    _optarg="${_optarg%%--*}"
    ### limit to just arguments up to next --option (no lazy support in POSIX)
    #
    return 0
  else
    return 1
  fi

オプションの後に他のオプションが続くスクリプトまたは関数呼び出しが指定されます...

otherfunction --option1 arg1 arg2 --option2 -- file1 /home/me/file2

otherfunction() によって受け入れられる各オプションに対して、optionArg() は次のように呼び出されます...

_optarg1="$(optionArg --option1 "$@")"
_optarg2="$(optionArg --option2 "$@")"
_optarg3="$(optionArg --        "$@")"

結果は…

_optarg1="arg1 arg2 "
_optarg2=""
_optarg3="file1 /home/me/file2"

関連情報