В вашем коде нет переменной списка. У вас есть строка.
Вызов test1
использует расширение $letterList
без кавычек. Это заставит оболочку разделить свое значение на несколько слов по пробелам, табуляциям и символам новой строки (по умолчанию ), и каждое слово будет подвергаться подстановке имени файла (, если оно содержит символы подстановки имени файла ). Результирующие слова передаются в test1
как отдельные аргументы.
В test1
вы помещаете только самый первый из этих аргументов в letterList
.
Если вы хотите передать строку из $letterList
как есть в test1
из test2
, вам нужно заключить ее расширение в двойные кавычки в вызове:
test1 "$letterList"
Между прочим, вы полагаетесь на то, что оболочка выполняет разбиение $letterList
значения в вашем цикле вtest1
(той же механике, которая вызывает вашу проблему ), но вы никогда не защищаете код от случайное выполнение подстановки имени файла (проверьте свой скрипт, например, test2 "A B C *"
чтобы понять, что я имею в виду ).
Если вы хотите передать список , а не одну строку, вызовите test2
со списком, а не со строкой:
test2 A B C "Hello World" "* *"
Затем в test2
передайте аргументы вtest1
:
#!/bin/sh
test1 "$@"
Здесь "$@"
расширит список позиционных параметров (до аргументов скрипта ), при этом каждый отдельный параметр будет заключен в кавычки.Это означает, что такой аргумент, как Hello World
, не будет разделен на несколько аргументов при вызове test1
, и строка * *
также не будет разделена на две части, и не произойдет подстановки имен файлов.
В test1
перебрать аргументы:
#!/bin/sh
for arg in "$@"; do
printf '%s\n' "$arg"
done
или
#!/bin/sh
for arg do
printf '%s\n' "$arg"
done
... или, если вы просто хотите напечатать аргументы, просто
#!/bin/sh
printf '%s\n' "$@"
Я везде использовал /bin/sh
в качестве оболочки, так как здесь нет ничего специфичного для bash
.
На самом деле очень легко написать что-то подобное. Например, вы можете получить файл с парами key=value
, а затем использовать его для замены содержимого шаблона. Например:
$ cat template
Hello $name,
someone told me you really like $thing!
$ cat values
name=Bob
thing=chocolate
Тогда ваш сценарий будет:
#!/bin/sh
## source the key/value pairs
. "$1"
## Replace them in the template
sed -e "s/\\\$name/$name/g" -e "s/\\\$thing/$thing/g" "$2"
И вы запускаете это так:
$ foo.sh /full/path/to/values template
Hello Bob,
someone told me you really like chocolate!
Конечно, это требует, чтобы вы знали имена ключей заранее. Альтернативой может быть:
#!/bin/sh
tmpFile=$(mktemp)
cp -- "$2" "$tmpFile"
while IFS='=' read -r key value; do
sed -i -e "s/\$$key/$value/g" "$tmpFile"
done < "$1"
cat "$tmpFile"
Другим вариантом может быть использование eval
для раскрытия переменных. Однако это опасно, поскольку открывает возможность внедрения кода, если значения в файле могут быть опасными. Если это не проблема для вас, попробуйте:
#!/bin/sh
## source the key/value pairs
. "$1"
## load the contents of the template
template="$(cat "$2")"
## Now print, but expanding the variables. We need to
## unset IFS to protect the newlines.
IFS=
eval echo \"$template\"