Coincidencia de expresión regular POSIX en la primera aparición de una cadena

Coincidencia de expresión regular POSIX en la primera aparición de una cadena

Tengo un script bash y solo quiero admitir opciones largas ("--option"). Una opción --option puede tener opcionalmente uno o más argumentos. Todas las palabras (cualquier cosa delimitada por espacios en blanco) hasta el primer '--' O el final de la cadena de línea de comando, pero sin incluirlo, se consideran "--argumentos de opción". Un espacio final en el resultado está bien. Se desea el máximo rendimiento ya que esta función es llamada por otras funciones para cada opción posible. Por lo tanto, intentamos evitar bucles de bash y comandos externos.

Luché durante muchas horas con el problema de la "primera aparición" hasta que encontréesta respuestaeso me recordó que POSIX (y por lo tanto bash) no admite operadores de expresiones regulares no codiciosos/perezosos.

¿Qué hacer?

Respuesta1

No puede analizar opciones con expresiones regulares de la manera que parece querer porque las opciones no se pasan en una cadena, sino en unlistade cuerdas. myscript --option foo bar -- quxtiene myscript, --option, foo, bary --como quxargumentos separados, ninguno de ellos contiene espacios en blanco.

Un bucle es el camino a seguir en bash.

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

Si el rendimiento es un gran problema, no deberías usar bash. Pruebe ksh en su lugar: es gratis, está disponible prácticamente en todas partes incluso si no está instalado de forma predeterminada y, a menudo, es significativamente más rápido que bash. Si todavía es demasiado lento, necesita un lenguaje de programación más sofisticado como Perl, Python o Ruby.

Respuesta2

Encontré esta solución bastante simple...

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

Dado un script o llamada de función con opciones seguidas de otras opciones como...

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

Para cada opción aceptada por otherfunction(), optionArg() se llamaría así...

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

Los resultados serían...

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

información relacionada