Как обернуть еще одну оболочку, передавая $ OPTIND как есть? - PullRequest
1 голос
/ 29 апреля 2011

Я пытаюсь обернуть bash-скрипт b скриптом a. Однако я хочу передать параметры, передаваемые a, также b, как они есть.

#!/bin/bash

# script a
./b ${@:$OPTIND}

Также будет напечатано $ 1 (если есть). Что проще всего не делать?

Так зовут:

./a -c -d 5 first-arg

Я хочу, чтобы b выполнило: ./b -c -d 5 # БЕЗ первого аргумента

Ответы [ 3 ]

1 голос
/ 29 апреля 2011

В bash вы можете создать массив, содержащий опции, и использовать этот массив для вызова вспомогательной программы.

call_b () {
  typeset -i i=0
  typeset -a a; a=()
  while ((++i <= OPTIND)); do   # for i=1..$OPTIND
    a+=("${!i}")                # append parameter $i to $a
  done
  ./b "${a[@]}"
}
call_b "$@"

В любой оболочке POSIX (ash, bash, ksh, zsh под эмуляцией sh или ksh,…) вы можете создать список с помощью "$1" "$2" … и использовать eval для установки различных позиционных параметров.

call_b () {
  i=1
  while [ $i -le $OPTIND ]; do
    a="$a \"\$$i\""
    i=$(($i+1))
  done
  eval set -- $a
  ./b "$@"
}
call_b "$@"

Как это часто бывает проще в zsh.

./b "${(@)@[1,$OPTIND]}"
0 голосов
/ 30 апреля 2011

Чтобы отделить параметры команды от обычных аргументов, вам необходимо знать, какие параметры принимают аргументы, а какие - отдельно.
В примере команда:

./a -c -d 5 first-arg
  • -c и -d могут быть автономными параметрами, а 5 first-arg обычными аргументами
  • 5 может быть аргументом для опции -d (кажется, это то, что вы имеете в виду)
  • -d может быть аргументом опции -c и (как в первом случае) 5 first-arg обычных аргументов.

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

#!/bin/bash

while getopts ab:cd: OPT; do
    case "$OPT" in
        a|b|c|d) : ;; # Don't do anything, we're just here for the parsing
        ?)  echo "Usage: $0 [-ac] [-b something] [-d something] [args...]" >&2
            exit 1 ;;
    esac
done

./b "${@:1:$((OPTIND-1))}"

Весь цикл while предназначен только для вычисления OPTIND. ab:cd: в команде getopts определяет, какие опции разрешены, а какие принимают аргументы (обозначенные двоеточиями). Загадочное окончательное выражение означает «элементы с 1 по OPTIND-1 массива аргументов, переданные как отдельные слова».

0 голосов
/ 29 апреля 2011

Почему вы используете ${@:$OPTIND}, а не просто $@ или $*?

Синтаксис ${parameter:index} говорит использовать index для разбора $parameter. Если вы используете $@, он будет использовать index в качестве индекса параметров.

$ set one two three four #Sets "$@"
$ echo $@
one two three four
$ echo ${@:0}
one two three four
$ echo ${@:1}
one two three four
$ echo ${@:2}
two three four

$OPTIND действительно используется только если вы используете getopts. Это количество раз getopts обрабатывает параметры в $@. Согласно справочной странице bash :

OPTIND устанавливается в 1 каждый раз, когда вызывается оболочка или сценарий оболочки.

Что может объяснить, почему вы постоянно получаете значение 1.


отредактировано в ответ на отредактированный вопрос

@ David - "./b $ @" по-прежнему печатает аргументы, переданные в (см. Q edit). Я хочу передать только параметры, а не аргументы

Итак, если я выполнил:

$ a -a foo -b bar -c fubar barfu barbar

Вы хотите перейти на b:

$ b -a foo -b bar -c fubar

но не

$ b -arg1 foo -arg2 bar -arg3 fubar barfu barbar

Это будет сложно ...

Есть ли причина, по которой вы не можете передать всю строку на b и просто игнорировать ее?

Я полагаю, что можно использовать регулярные выражения:

$ echo "-a bar -b foo -c barfoo foobar" | sed 's/\(-[a-z] [^- ][^- ]*\)  *\([^-][^-]*\)$/\1/'
-a bar -b foo -c barfoo

Я не могу ручаться, что это регулярное выражение будет работать во всех ситуациях (т. Е. Что, если нет параметров?). По сути, я привязываю его к концу строки, а затем сопоставляю для последнего параметра и аргумента и остальной части строки. Я делаю замену только с последним параметром и аргументом.

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

...