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"