12

"Передача всех аргументов в Bash-скрипте"

16

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

Например, имя моего скрипта — foo.sh, и он вызывает bar.sh.

Содержимое foo.sh:

bar $1 $2 $3 $4

Как мне сделать это, не указывая явно каждый параметр?

5 ответ(ов)

19

В данном случае я рекомендую использовать "$@" вместо простого $@, если вы хотите, чтобы ваши параметры передавались так же, как были получены.

Обратите внимание на следующий пример:

Скрипт no_quotes.sh

#!/bin/bash
echo_args.sh $@

Скрипт quotes.sh

#!/bin/bash
echo_args.sh "$@"

Скрипт echo_args.sh

#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4

Теперь давайте посмотрим, что произойдет при запуске этих скриптов:

  1. Запуск ./no_quotes.sh first second:

    Received: first
    Received: second
    Received:
    Received:
    
  2. Запуск ./no_quotes.sh "one quoted arg":

    Received: one
    Received: quoted
    Received: arg
    Received:
    
  3. Запуск ./quotes.sh first second:

    Received: first
    Received: second
    Received:
    Received:
    
  4. Запуск ./quotes.sh "one quoted arg":

    Received: one quoted arg
    Received:
    Received:
    Received:
    

Как видно из результатов, когда мы передаем параметры без кавычек ($@), Bash разбивает аргументы на отдельные слова, если они содержат пробелы. В случае с "$@" все аргументы передаются как есть, что позволяет сохранить их целостность. Поэтому использование "$@" — это лучший подход, когда вы работаете с аргументами, содержащими пробелы или другие специальные символы.

5

В bash и других оболочках, подобных Bourne:

bar "$@"

Команда "$@" используется для передачи всех аргументов скрипта или функции bar. Она экранирует аргументы так, чтобы они корректно обрабатывались даже если они содержат пробелы или специальные символы. То есть, "$@" передает каждый аргумент как отдельный параметр, что отличается от $*, который объединяет все аргументы в одну строку. Это гарантирует, что каждый аргумент будет правильно интерпретирован в функции или команде bar.

1

В этом ответе мы рассмотрим различия между "$@", $@, "*", и * в bash, особенно в контексте передачи аргументов в скрипты.

Текст скрипта test.sh:

#!/usr/bin/env bash
echo "================================="

echo "Quoted DOLLAR-AT"
for ARG in "$@"; do
    echo $ARG
done

echo "================================="

echo "NOT Quoted DOLLAR-AT"
for ARG in $@; do
    echo $ARG
done

echo "================================="

echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
    echo $ARG
done

echo "================================="

echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
    echo $ARG
done

echo "================================="

Теперь давайте запустим этот скрипт с различными аргументами:

./test.sh "arg with space one" "arg2" arg3

Результат выполнения будет следующим:

=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================

Объяснение:

  1. "$@":

    • Аргументы автоматически обрабатываются как отдельные элементы (каждый аргумент остается целым, включая пробелы внутри). Это значит, что если вы передали аргумент с пробелами, он будет распечатан на новой строке в цикле.
  2. $@ (без кавычек):

    • В этом случае bash разбивает все аргументы на отдельные слова. Если переданный аргумент содержит пробелы, они будут считаться разделителями, и каждый "слово" будет распечатано отдельно.
  3. "$*":

    • Соединяет все аргументы в одну строку, разделённую первым символом IFS (обычно пробел). Таким образом, вывод для этого случая будет одной строкой, содержащей все аргументы, включая пробелы внутри.
  4. $* (без кавычек):

    • Работает аналогично "$*", разбивая аргументы на слова и игнорируя пробелы, при этом каждый элемент будет распечатан отдельно.

Резюме:

  • Использование "$@" предпочтительнее, когда вам нужно сохранить аргументы, содержащие пробелы, как отдельные единицы.
  • В случае "$*" все аргументы будут объединены в одну строку. Выбор использования того или иного механизма зависит от того, как вы хотите обрабатывать аргументы в вашем скрипте.
0

Этот сценарий на Bash позволяет вам видеть, как аргументы передаются в ваш скрипт. Вот перевод вашего сообщения в стиле ответа на StackOverflow:

#!/usr/bin/env bash
while [ "$1" != "" ]; do
  echo "Получено: ${1}" && shift;
done;

Этот скрипт будет выводить каждый аргумент, переданный ему при запуске, в виде строки "Получено: <аргумент>". Цикл while продолжается до тех пор, пока не будут обработаны все аргументы. Команда shift сдвигает позиционные параметры влево, демонтируя текущий аргумент ($1) и позволяя следующему аргументу занять его место.

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

0

Когда вы включаете $@ в строку, заключённую в кавычки, вместе с другими символами, поведение может быть неожиданным, особенно когда имеется несколько аргументов. В таких случаях только первый аргумент будет включен в кавычки.

Например, рассмотрим следующий скрипт:

#!/bin/bash
set -x
bash -c "true foo $@"

Если вы запустите этот скрипт с аргументами, например:

$ bash test.sh bar baz

Вы получите следующий вывод:

+ bash -c 'true foo bar' baz

Как видно, только первый аргумент (bar) попадает в кавычки, а остальные (baz) выходят за пределы.

Теперь, если сначала присвоить $@ другой переменной, например:

#!/bin/bash
set -x
args="$@"
bash -c "true foo $args"

При запуске с теми же аргументами:

$ bash test.sh bar baz

Вы получите:

+ args='bar baz'
+ bash -c 'true foo bar baz'

В этом случае все аргументы успешно передаются в команду, так как мы сначала записали их в переменную args, и при подстановке в строку кавычки больше не влияют на разделение аргументов.

Таким образом, рекомендуется использовать переменные для хранения аргументов, если вы хотите избежать неожиданных результатов при использовании $@ в кавычках.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь