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

Я пытаюсь написать функцию в 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 $*

person DonGar    schedule 29.04.2010    source источник
comment
Я немного запутался, вам нужны аргументы без их передачи?   -  person Ravi Vyas    schedule 30.04.2010
comment
Да, дело в том, чтобы получить аргументы командной строки из функции, не передавая их в качестве функциональных аргументов. Это связано с ситуацией обработки ошибок, в которой я хочу выполнять обработку ошибок на основе аргументов командной строки независимо от аргументов, переданных в функцию.   -  person DonGar    schedule 10.05.2010
comment
К вашему сведению, $* очень глючный - он изменит ./yourScript "first argument" "second argument" на ./yourscript "first" "argument" "second" "argument" или изменит ./yourscript '*.txt' на что-то вроде ./yourscript one.txt two.txt, несмотря на кавычки.   -  person Charles Duffy    schedule 19.05.2018


Ответы (8)


Мое прочтение справочного руководства Bash говорит, что этот материал захвачен в BASH_ARGV, хотя он говорит о стеке много.

#!/bin/bash

shopt -s extdebug

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
fbaz bar boo arg2 arg1 arg0
g goo gar gaz
ggaz gar goo arg2 arg1 arg0
f
fgaz gar goo arg2 arg1 arg0
person mcarifio    schedule 29.04.2010
comment
Обратите внимание, что такая переборка массива приводит к тому, что аргументы находятся в обратном порядке от командной строки. - person Andrew Backer; 30.11.2011
comment
${BASH_ARGV[*]} возможно должно быть "${BASH_ARGV[@]}" с двойными кавычками и @ - person tripleee; 14.04.2021

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

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

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

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

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

person stigi    schedule 29.04.2010
comment
Это не решает вопрос - он спрашивает о передаче аргументов командной строки функции оболочки. - person Cascabel; 30.04.2010
comment
@Jefromi, на самом деле, это отлично отвечает на вопрос. Вы можете использовать массив args внутри функции, если вы предварительно инициализируете его, как описано. - person vadipp; 04.02.2013
comment
Я нахожу это намного чище, чем перебор аргументов. - person Félix Adriyel Gagnon-Grenier; 12.05.2017
comment
Это просто и легко. Отличный ответ. Вы опубликовали это более 7 лет назад, так что привет из будущего: июль 2017 года. - person SDsolar; 14.07.2017
comment
Еще лучше было бы цитировать как echo "${args[0]} ${args[1]} ${args[2]}", или аргументы подлежат расширению имени файла. - person Benjamin W.; 13.08.2018

#!/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 $#

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

person Ravi Vyas    schedule 29.04.2010

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

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

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

commandline_args=("$@")

my_function

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

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

person Cascabel    schedule 29.04.2010

Можно сделать это и так

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

Теперь вызовите свой скрипт, например

./function_test.sh argument1 argument2
person Vikash Singh    schedule 14.07.2016
comment
function print() { представляет собой смесь двух разных форм объявления функций: function print {, который представляет собой устаревший синтаксис ksh, который bash поддерживает для обратной совместимости с ksh до POSIX (то есть до 1991 года), и print() {, который стандартизирован по POSIX. Рассмотрите возможность использования одного или другого для более широкой совместимости с другими оболочками; см. также wiki.bash-hackers.org/scripting/obsolete - person Charles Duffy; 19.05.2018

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

#! /bin/bash

function init(){   ORIGOPT= "- $@ -"  }

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

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

person cabonamigo    schedule 15.01.2020

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

#!/bin/bash
function print()
{
    while [ $# -gt 0 ]
    do
        echo "$1"
        shift 1
    done
}
print "$@"
person Marin Alcaraz    schedule 19.11.2014
comment
function print() { представляет собой смесь двух разных форм объявления функций: function print {, который представляет собой устаревший синтаксис ksh, который bash поддерживает для обратной совместимости с ksh до POSIX (то есть до 1991 года), и print() {, который стандартизирован по POSIX. Рассмотрите возможность использования одного или другого для более широкой совместимости с другими оболочками; см. также wiki.bash-hackers.org/scripting/obsolete - person Charles Duffy; 19.05.2018

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

# first you define your function 
function func_ImportantPrints() {
    printf '%s\n' "$1" 
    printf '%s\n' "$2" 
    printf '%s\n' "$3" 
} 
# then when you make your function call you do this:  
func_ImportantPrints "$@" 

Это полезно независимо от того, отправляете ли вы аргументы в main или какую-либо функцию, например func_parseArguments (функция, содержащая оператор case, как показано в предыдущих примерах) или любую функцию в скрипте.

person JamesIsIn    schedule 23.05.2021