IFS
указывает, как разделить значения переменных в заменах без кавычек. Это относится как к $row
, так и к $myscript
.
Если вы хотите использовать IFS
для разделения, что удобно в простом sh, вам нужно изменить значение IFS
или сделать так, чтобы оно требовало того же значения. В этом конкретном случае вы можете легко добиться того же значения, определив myScript
как myScript="/usr/bin/java|-version"
. Кроме того, вы можете вовремя изменить значение IFS
. Обратите внимание, что в обоих случаях подстановка без кавычек не просто разделяет значение с помощью IFS
, но также интерпретирует каждую часть как шаблон подстановки и заменяет его списком совпадающих имен файлов, если таковые имеются. Это означает, что если ваш файл CSV содержит строку вида
foo|*|bar
тогда строка будет не foo
, *
, bar
, а foo
, каждое имя файла в текущем каталоге bar
. Чтобы обрабатывать данные таким образом, вам нужно отключить с помощью set -f
. Также помните, что read
считывает строки продолжения, когда строка заканчивается обратной косой чертой, и удаляет начальные и конечные IFS
символы. Используйте IFS= read -r
, чтобы отключить эти два поведения.
myScript="/usr/bin/java -version"
set -f
while IFS= read -r row
do
$myScript
IFS='|'
for column in $row
do
IFS=' '
$myScript
done
done
Однако есть лучшие способы полностью избежать разделения IFS. Не храните команду в строке, разделенной пробелами: она не работает в сложных случаях, например, в командах, которым требуется аргумент, содержащий пробел. Существует три надежных способа хранения команды:
Сохраните команду в функции. Это самый естественный подход. Выполнение команды — это код; вы определяете код в функции. Вы можете ссылаться на аргументы функции вместе как "$@"
.
myScript () {
/usr/bin/java -version "$@"
}
…
myScript extra_argument_1 extra_argument_2
Сохраните имя исполняемой команды и ее аргументы в массиве.
myScript=(/usr/bin/java -version)
…
"${myScript[@]}" extra_argument_1 extra_argument_2
Сохраните команду оболочки, то есть то, что предназначено для анализа оболочкой. Чтобы оценить шелл-код в строке, используйте eval
. Обязательно заключайте аргумент в кавычки, как и любое другое раскрытие переменной, чтобы избежать преждевременного раскрытия подстановочных знаков. Этот подход более сложен, так как требует тщательного цитирования. Это действительно полезно, только когда вам нужно сохранить команду в строке, например, потому что она входит в качестве параметра вашего скрипта. Обратите внимание, что вы не можете разумно передавать дополнительные аргументы таким образом.
myScript='/usr/bin/java -version'
…
eval "$myScript"
Кроме того, поскольку вы используете ksh, а не обычный sh, вам не нужно использовать IFS
для разделения строки ввода. Вместо этого используйте read -A
для прямого разделения на массив.
#!/usr/bin/ksh
CSV_FILE=${1}
myScript=(/usr/bin/java -version)
while IFS='|' read -r -A columns
do
"${myScript[@]}"
for column in "${columns[@]}"
do
"${myScript[@]}"
done
done <"$CSV_FILE"
person
Gilles 'SO- stop being evil'
schedule
08.09.2018