Як отримати доступ до аргументів командного рядка абонента всередині функції?


95

Я намагаюся написати функцію в 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незважаючи на лапки.
Чарльз Даффі,

Відповіді:


46

У своєму прочитанні посібника з 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
Зауважте, що повторення такого типу масиву призводить до того, що аргументи будуть у зворотному порядку з командного рядка.
Andrew Backer,

93

Якщо ви хочете мати свої аргументи стиль C (масив аргументів + ​​кількість аргументів), ви можете використовувати $@і $#.

$#дає кількість аргументів.
$@дає всі аргументи. Ви можете перетворити це на масив за допомогою args=("$@").

Так, наприклад:

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

Зауважте, що ${args[0]}насправді тут є перший аргумент, а не назва вашого сценарію.


5
Це не стосується питання - це питання про передачу аргументів командного рядка разом із функцією оболонки.
Каскабель

6
@Jefromi, насправді, він ідеально відповідає на питання. Ви можете використовувати argsмасив всередині функції, якщо попередньо ініціалізувати його, як описано.
vadipp

1
Я вважаю це набагато чистішим, ніж ітерація над арґами.
Фелікс Ганьон-Греньє

1
Це просто і легко. Чудова відповідь. Ви публікували це понад 7 років тому, так що привіт від майбутнього: липень 2017
SDsolar

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

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

Редагувати: дивіться, будь ласка, мій коментар до питання


16

Коментар Раві - це, по суті, відповідь. Функції беруть власні аргументи. Якщо ви хочете, щоб вони були такими ж, як аргументи командного рядка, ви повинні передати їх. Інакше ви чітко викликаєте функцію без аргументів.

Це означає, що ви можете, якщо ви хочете зберігати аргументи командного рядка в глобальному масиві, щоб використовувати їх в інших функціях:

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 підтримує для зворотної сумісності з pre-POSIX (тобто, до 1991 р.) ksh, і 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 підтримує для зворотної сумісності з pre-POSIX (тобто, до 1991 р.) ksh, і print() {який стандартизований POSIX. Подумайте про те, щоб використовувати ту чи іншу для ширшої сумісності з іншими оболонками; дивіться також wiki.bash-hackers.org/scripting/obsolete
Чарльз Даффі

1

Моє рішення:

Створіть скрипт функції, який викликається раніше, ніж усі інші функції, не передаючи йому жодних аргументів, наприклад:

! / бін / баш

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

Зважаючи на це, ви можете зателефонувати init і використовувати var ORIGOPT за потреби, як плюс, я завжди призначаю новий var і копіюю вміст ORIGOPT в моїх нових функціях, таким чином ви можете бути впевнені, що ніхто не збирається його торкатися або зміни це.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.