Как получить доступ к аргументам командной строки вызывающего абонента внутри функции?


102

Я пытаюсь написать функцию в bash, которая будет обращаться к аргументам командной строки сценария, но они заменяются позиционными аргументами функции. Есть ли способ для функции получить доступ к аргументам командной строки, если они не переданы явно?

# Demo function
function stuff {
  echo $0 $*
}

# Echo's the name of the script, but no command line arguments
stuff

# Echo's everything I want, but trying to avoid
stuff $*

3
Я немного смущен, вы хотите, чтобы аргументы не передавались?
Рави Вьяс,

4
Да, дело в том, чтобы получить аргументы командной строки изнутри функции, не передавая их в качестве функциональных аргументов. Это связано с ситуацией обработки ошибок, в которой я хочу выполнять обработку ошибок на основе аргументов командной строки независимо от аргументов, переданных в функцию.
DonGar

FYI, $*очень глючит - он изменится ./yourScript "first argument" "second argument"на ./yourscript "first" "argument" "second" "argument"или изменится ./yourscript '*.txt'на что-то вроде, ./yourscript one.txt two.txtнесмотря на кавычки.
Чарльз Даффи

Ответы:


48

Я читал руководство по bash ref, в котором говорится, что все это записано в BASH_ARGV, хотя много говорится о «стеке».

#!/bin/bash

function argv {
    for a in ${BASH_ARGV[*]} ; do
      echo -n "$a "
    done
    echo
}

function f {
    echo f $1 $2 $3
    echo -n f ; argv
}

function g {
    echo g $1 $2 $3
    echo -n g; argv
    f
}

f boo bar baz
g goo gar gaz

Сохранить в f.sh

$ ./f.sh arg0 arg1 arg2
f boo bar baz
farg2 arg1 arg0 
g goo gar gaz
garg2 arg1 arg0 
f
farg2 arg1 arg0 

5
Обратите внимание, что при повторении такого массива аргументы располагаются в обратном порядке из командной строки.
Эндрю Бэкер

96

Если вы хотите, чтобы ваши аргументы были в стиле C (массив аргументов + количество аргументов), вы можете использовать $@и $#.

$#дает вам количество аргументов.
$@дает вам все аргументы. Вы можете превратить это в массив с помощью args=("$@").

Так например:

args=("$@")
echo $# arguments passed
echo ${args[0]} ${args[1]} ${args[2]}

Обратите внимание, что здесь ${args[0]}фактически находится 1-й аргумент, а не имя вашего скрипта.


5
Это не решает вопрос - он спрашивает о передаче аргументов командной строки функции оболочки.
Cascabel

6
@Jefromi, на самом деле, отлично отвечает на вопрос. Вы можете использовать argsмассив изнутри функции, если вы инициализируете его заранее, как описано.
vadipp 04

1
Я считаю, что это намного чище, чем повторение аргументов.
Феликс Ганьон-Гренье,

1
Это просто и легко. Отличный ответ. Вы разместили это более 7 лет назад, так что привет из будущего: июль 2017
SDsolar

Еще лучше было бы цитировать вроде echo "${args[0]} ${args[1]} ${args[2]}", или аргументы подлежат расширению имени файла.
Бенджамин В.

18
#!/usr/bin/env bash

echo name of script is $0
echo first argument is $1
echo second argument is $2
echo seventeenth argument is $17
echo number of arguments is $#

Изменить: пожалуйста, посмотрите мой комментарий к вопросу


17

Комментарий Рави - это, по сути, ответ. Функции принимают свои собственные аргументы. Если вы хотите, чтобы они были такими же, как аргументы командной строки, вы должны передать их. В противном случае вы явно вызываете функцию без аргументов.

Тем не менее, вы можете, если хотите, сохранить аргументы командной строки в глобальном массиве для использования в других функциях:

my_function() {
    echo "stored arguments:"
    for arg in "${commandline_args[@]}"; do
        echo "    $arg"
    done
}

commandline_args=("$@")

my_function

Вы должны получить доступ к аргументам командной строки с помощью commandline_argsпеременной, а не $@, $1, $2и т.д., но они доступны. Я не знаю, как назначить напрямую массиву аргументов, но если кто-то знает такой, пожалуйста, просветите меня!

Также обратите внимание на то, как я использовал и цитировал $@- это то, как вы гарантируете, что специальные символы (пробелы) не испорчены.


6
# Save the script arguments
SCRIPT_NAME=$0
ARG_1=$1
ARGS_ALL=$*

function stuff {
  # use script args via the variables you saved
  # or the function args via $
  echo $0 $*
} 


# Call the function with arguments
stuff 1 2 3 4

2

Можно и так

#!/bin/bash
# script_name function_test.sh
function argument(){
for i in $@;do
    echo $i
done;
}
argument $@

Теперь назовите свой сценарий как

./function_test.sh argument1 argument2

function print() {представляет собой смесь двух различных форм объявления функций - function print {это унаследованный синтаксис ksh, который bash поддерживает для обратной совместимости с ksh до POSIX (то есть до 1991 года), и print() {, который стандартизирован для POSIX. Рассмотрите возможность использования того или другого для более широкой совместимости с другими оболочками; см. также wiki.bash-hackers.org/scripting/obsolete
Чарльз Даффи,

1

Вы можете использовать ключевое слово shift (оператор?), Чтобы перебирать их. Пример:

#!/bin/bash
function print()
{
    while [ $# -gt 0 ]
    do
        echo $1;
        shift 1;
    done
}
print $*;

2
function print() {представляет собой смесь двух различных форм объявления функций - function print {это унаследованный синтаксис ksh, который bash поддерживает для обратной совместимости с ksh до POSIX (то есть до 1991 года), и print() {, который стандартизирован для POSIX. Рассмотрите возможность использования того или другого для более широкой совместимости с другими оболочками; см. также wiki.bash-hackers.org/scripting/obsolete
Чарльз Даффи,

1

Мое решение:

Создайте сценарий функции, который вызывается раньше, чем все другие функции, без передачи ему аргументов, например:

! / bin / bash

функция init () {ORIGOPT = "- $ @ -"}

После этого вы можете вызвать init и использовать ORIGOPT var по мере необходимости, в качестве плюса я всегда назначаю новую var и копирую содержимое ORIGOPT в свои новые функции, так что вы можете быть уверены, что никто не коснется его или Измени это.

Я добавил пробелы и дефисы, чтобы упростить анализ с помощью sed -E, также bash не будет передавать его как ссылку и заставит ORIGOPT расти, поскольку функции вызываются с большим количеством аргументов.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.