
Привет ВСЕМ и спасибо заранее.
Я искал на форуме информацию о своей ситуации и не смог найти решение. У меня есть скрипт, которому я передаю аргументы/опции/параметры в командной строке. В одном из значений есть пробел, который я заключил в двойные кавычки. Возможно, будет проще привести пример. Извините за использование аргументов/опций/параметров.
$: ./test1.ksh -n -b -d "Home Videos"
Моя проблема в установке переменной на "Home Videos" и их совместном использовании. В моем примере -d указывает каталог. Не все каталоги имеют пробелы, но некоторые имеют в моем случае.
Это пример кода, который не работает так, как я ожидал.
#!/bin/ksh
Function1()
{
echo "Number of Args in Function1: $#"
echo "Function1 Args: $@"
SetArgs $*
}
SetArgs()
{
echo -e "\nNumber of Args in SetArgs: $#"
echo "SetArgs Args: $@"
while [ $# -gt 0 ]
do
case $1 in
-[dD])
shift
export DirectoryName=$1
;;
-[nN])
export Var1=No
shift
;;
-[bB])
export Var2=Backup
shift
;;
*)
shift
;;
esac
done
Function2
}
Function2()
{
echo "Directory Name: ${DirectoryName}"
}
Function1 $*
Когда я запускаю это, я получаю только Home для DirectoryName вместо Home Videos. Видно ниже.
$ ./test1.ksh -n -b -d "Home Videos"
Number of Args in Function1: 5
Function1 Args: -n -b -d Home Videos
Number of Args in SetArgs: 5
SetArgs Args: -n -b -d Home Videos
Var1 is set to: No
Var2 is set to: Backup
Directory Name: Home
Я ожидаю, но не могу добиться следующего:
$ ./test1.ksh -n -b -d "Home Videos"
Number of Args in Function1: 4
Function1 Args: -n -b -d "Home Videos"
Number of Args in SetArgs: 4
SetArgs Args: -n -b -d "Home Videos"
Var1 is set to: No
Var2 is set to: Backup
Directory Name: Home Videos <-- Without double quotes in the final usage.
Буду очень признателен за любую помощь... Я пробовал экранировать двойные кавычки, но безуспешно.
Спасибо за ваше время и усилия, которые вы потратили, чтобы помочь мне разобраться в этом вопросе.
С уважением, Дэниел.
решение1
Использование $*
или $@
отсутствие кавычекникогдаимеет смысл.
"$*"
представляет собой конкатенацию позиционных параметров с первым символом (или байтом в зависимости от оболочки) $IFS
, "$@"
представляет собой список позиционных параметров.
Если не заключено в кавычки, то это то же самое, но подлежит разделению+глобализации (или только удалению пустых значений с помощью zsh
), как и любое другое раскрытие параметра без кавычек (некоторые оболочки также разделяют аргументы, $*
даже если $IFS
они пусты).
Здесь вы хотите передать список аргументовкак естьк вашей функции, так что это:
SetArgs "$@"
[...]
Function1 "$@"
Обратите внимание, что в ksh88 $IFS
для правильной работы необходимо наличие символа пробела (что происходит по умолчанию) (ошибка, унаследованная от оболочки Bourne, исправлена в ksh93).
Также обратите внимание, что в некоторых реализациях ksh
(например, в старых версиях zsh
в ksh
эмуляции)
export DirectoryName=$1
это случай вызова split+glob. export
это одна из тех команд в оболочках типа Korn, которая может оценивать код оболочкичерез арифметическую оценку в индексах массива), так что этоодин из тех случаев, когда важно заключать переменные в кавычки, чтобы избежать уязвимостей, связанных с внедрением команд.
Пример:
$ (exec -a ksh zsh-4.0.1 -c 'export x=$a' ksh 'foo psvar[0`uname>&2`]')
Linux
Обратите внимание, что [ $# -gt 0 ]
это еще один вызов split+glob, который не имеет смысла (вероятность возникновения проблем меньше, по крайней мере, при значении по умолчанию $IFS
).
решение2
Рассматривали ли вы возможность использования getopts
встроенной команды оболочки для анализа ваших аргументов (как предложил, например, @Stéphane Chazelas вэтот комментарий)? Это избавит вас от многих хлопот.
В вашем случае соответствующий код будет выглядеть следующим образом:
while getopts "nbd:" argname
do
case "$argname" in
n) Var1="No" ;;
b) Var2="Backup" ;;
d) DirectoryName ="$OPTARG" ;;
?) echo -e "usage is..."
exit 1 ;;
esac
done