Перебор опций параметров командной строки до следующего параметра

С GNU grepвы можете сделать:

grep -Eo '\S+\s+\S+\s+\S+\s*$'

Это позволит сохранить интервал во входных данных. Обратите внимание, что строки, содержащие менее 3 полей, пропускаются.

POSIX эквивалентом будет:

S='[^[:space:]]\{1,\}' s='[[:space:]]\{1,\}'
sed -n "s/$S$s$S$s${S}[[:space:]]*$/\\
&/;s/.*\n//p"
4
15.09.2021, 19:00
3 ответа

Разбор аргумента может быть утомительным. Я бы посоветовал вам использовать getopt (1). Отсюда вы можете указать один и тот же флаг несколько раз:

datt -p Package1 -p Package2 -p Package3 --build

Если по какой-то причине вы не можете повторно использовать флаг (не уверен, что это будет, но... )вы также можете передать аргумент как отдельный элемент и разбить его на пробел:

datt -p "Package1 Package2 Package3" --build
9
15.09.2021, 20:01

Обычно разумнее всего перебирать все параметры в одном цикле и размещать их в нужных местах. Обычно я не выполняю обработку из цикла синтаксического анализа аргумента -, но это может иметь смысл, если порядок параметров имеет значение.

. такой цикл (для Bash или zsh):

#!/usr/bin/zsh
packages=()
while [ "$#" -gt 0 ]; do
    case $1 in
    -p)      echo "p option seen...";;
    --build) echo "--build option seen after ${#packages[@]} packages...";;
    *)       echo "adding package '$1'";
             packages+=("$1");;
    esac
    shift;
done

typeset -p packages;

дал бы:

$ zsh dattest.sh -p foo bar doo --build
p option seen...
adding package 'foo'
adding package 'bar'
adding package 'doo'
--build option seen after 3 packages...
typeset -a packages=( foo bar doo )
5
15.09.2021, 20:47

Для такого разбора проще использовать цикл while и shiftпока массив не станет пустым.

packages=()
while (($#)); do
  case $1 in
    -p)
      while shift; [[ $1 != -* ]]; do
        packages+=($1)
      done
    …
  esac
  shift
done

Вы можете использовать флаг нижнего индексаiдля выполнения внутреннего цикла в поисках следующей опции. $array[(i)PATTERN]— индекс первого элемента, соответствующего PATTERN,с индексами, начинающимися с 1, поэтому вычтите 1, чтобы получить количество оставшихся элементов. Если совпадения для PATTERNнет, значение равно единице плюс индекс последнего элемента, именно поэтому такой код работает и в этом случае.

packages=()
while (($#)); do
  case $1 in
    -p) ((n = $@[(i)-*] - 1)); packages+=($@[1,$n]); shift $n;;
    …
  esac
  shift
done

Синтаксис, который вы описываете, не соответствует -стандарту. По этой причине я не рекомендую :это сбивать с толку ваших пользователей. Обычно datt -p Package1 Package2 Package3 --buildделает то же самое, что и datt -p Package1 Package2 --build Package3.

5
15.09.2021, 21:13

Теги

Похожие вопросы