Передача опций/аргументов/параметров с пробелами из скрипта в функцию внутри

Передача опций/аргументов/параметров с пробелами из скрипта в функцию внутри

Привет ВСЕМ и спасибо заранее.

Я искал на форуме информацию о своей ситуации и не смог найти решение. У меня есть скрипт, которому я передаю аргументы/опции/параметры в командной строке. В одном из значений есть пробел, который я заключил в двойные кавычки. Возможно, будет проще привести пример. Извините за использование аргументов/опций/параметров.

$:  ./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

Связанный контент