Регулярное выражение POSIX соответствует первому вхождению строки

Регулярное выражение POSIX соответствует первому вхождению строки

У меня есть скрипт bash, и я хочу поддерживать только длинные параметры ("--option"). --option может иметь один или несколько аргументов. Все слова (все, что разделено пробелами) до, но не включая первый '--' ИЛИ ​​конец строки командной строки, считаются "--option-arguments". Конечный пробел в результате допустим. Желательна максимальная производительность, поскольку эта функция вызывается другими функциями для каждого возможного параметра. Таким образом, пытаясь избежать циклов bash и внешних команд.

Много часов боролся с проблемой «первого появления», пока не нашелэтот ответэто напомнило мне, что POSIX (и, следовательно, bash) не поддерживает нежадные/ленивые операторы регулярных выражений.

Что делать?

решение1

Вы не можете анализировать параметры с помощью регулярных выражений так, как вам хотелось бы, поскольку параметры передаются не в строке, а всписокстрок. myscript --option foo bar -- quxимеет myscript, --option, foo, и как отдельные аргументы, ни один из которых не содержит пробелов bar.--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"

Связанный контент