POSIX-Regular-Ausdruck-Übereinstimmung beim ersten Vorkommen einer Zeichenfolge

POSIX-Regular-Ausdruck-Übereinstimmung beim ersten Vorkommen einer Zeichenfolge

Ich habe ein Bash-Skript, das nur lange Optionen unterstützen soll („--option“). Eine „--option“ kann optional ein oder mehrere Argumente haben. Alle Wörter (alles, was durch Leerzeichen getrennt ist) bis zum ersten „--“ ODER dem Ende der Befehlszeilenzeichenfolge, jedoch nicht einschließlich, werden als „--option-arguments“ betrachtet. Ein nachstehendes Leerzeichen im Ergebnis ist in Ordnung. Maximale Leistung ist erwünscht, da diese Funktion von anderen Funktionen für jede mögliche Option aufgerufen wird. Daher versuche ich, Bash-Schleifen und externe Befehle zu vermeiden.

Viele Stunden lang habe ich mit dem Problem des "ersten Auftretens" gekämpft, bis ich herausgefunden habediese Antwortdas hat mich daran erinnert, dass POSIX (und damit auch Bash) keine nicht gierigen/trägen Regex-Operatoren unterstützt.

Was zu tun?

Antwort1

Sie können Optionen nicht mit regulären Ausdrücken analysieren, wie Sie es anscheinend möchten, da Optionen nicht in einer Zeichenfolge übergeben werden, sondern in einemListevon Zeichenfolgen. myscript --option foo bar -- quxhat myscript, --option, foo, bar, --und quxals separate Argumente, von denen keines Leerzeichen enthält.

In Bash ist eine Schleife der richtige Weg.

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

Wenn die Leistung ein so großes Problem darstellt, sollten Sie Bash nicht verwenden. Versuchen Sie stattdessen Ksh – es ist kostenlos, praktisch überall verfügbar, auch wenn es nicht standardmäßig installiert ist, und es ist oft deutlich schneller als Bash. Wenn das immer noch zu langsam ist, benötigen Sie eine ausgefallenere Programmiersprache wie Perl, Python oder Ruby.

Antwort2

Habe diese ziemlich einfache Lösung gefunden …

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

Gegeben sei ein Skript- oder Funktionsaufruf mit Optionen, gefolgt von weiteren Optionen wie ...

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

Für jede von otherfunction() akzeptierte Option würde optionArg() wie folgt aufgerufen:

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

Die Ergebnisse wären ...

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

verwandte Informationen