correspondência de expressão regular POSIX na primeira ocorrência de string

0

Eu tenho o script bash que eu quero apenas suportar opções longas ("--option"). Uma opção pode ter opcionalmente um ou mais argumentos. Todas as palavras (qualquer coisa delimitada por espaço em branco) até, mas não incluindo, o primeiro '-' OU o final da cadeia da linha de comando são consideradas "--option-arguments". Um espaço à direita no resultado está bem. O desempenho máximo é desejado, pois essa função é chamada por outras funções para cada opção possível. Assim, tentando evitar loops bash e comandos externos.

Lutei por muitas horas com o problema da "primeira ocorrência" até encontrar esta resposta que me lembrou que POSIX (e assim, bash) não suporta operadores de regex nongreedy / lazy.

O que fazer?

(editado com base no comentário)

    
por DocSalvager 15.02.2016 / 15:15

2 respostas

1

Você não pode analisar opções com expressões regulares do jeito que você deseja, porque as opções não são passadas em uma string, mas em uma lista de strings. myscript --option foo bar -- qux tem myscript , --option , foo , bar , -- e qux como argumentos separados, nenhum deles contendo espaços em branco.

Um loop é o caminho a percorrer no bash.

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

Se o desempenho é um grande problema, você não deveria estar usando o bash. Experimente o ksh em vez disso - é gratuito, disponível em praticamente todos os lugares, mesmo que não seja instalado por padrão, e geralmente é significativamente mais rápido que o bash. Se ainda for muito lento, você precisa de uma linguagem de programação mais sofisticada, como Perl, Python ou Ruby.

    
por 16.02.2016 / 02:23
-1

A frustração levou a pensar fora da caixa de expressões regulares e encontrou essa solução bastante simples ...

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 um script ou chamada de função com opções seguidas por outras opções como ...

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

Para cada opção aceita por otherfunction (), optionArg () seria chamado como ...

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

Os resultados seriam ...

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

Espero que isso ajude alguém a ter problemas semelhantes.

Por favor, informe sobre quaisquer casos de canto descobertos onde isto falhar.

    
por 15.02.2016 / 15:15