Вопрос или проблема
Из команды я получаю некоторые аргументы, которые хочу предложить пользователю с помощью оператора select в bash в оболочке. Аргументы, переданные командой, могут содержать пробелы и, следовательно, защищены кавычками. Вот упрощенный пример.
Это работает, как и ожидалось:
select opt in a b "c d"
do
echo $opt
break
done
Вывод такой, как и ожидалось:
1) a
2) b
3) c d
#?
Но с выводом из команды в переменной это не работает, как ожидалось:
opts="a b \"c d\""
select opt in $opts
do
echo $opt
break
done
Хотя $opts содержит то же самое, что и жестко закодированное во втором примере select, вывод отличается:
1) a
2) b
3) "c
4) d"
#?
Итак, дело не в том, что bash съел кавычки. Они сохраняются, но кавычки не охватывают аргумент так, как это было, когда я закодировал их жестко. Как я уже написал, я получаю аргументы как вывод из команды. Они могут содержать пробелы и, следовательно, уже защищены кавычками. Как мне передать их в одном целом к оператору ‘select’? Дело не в одиночных и двойных кавычках. С одиночными кавычками происходит то же самое:
1) a
2) b
3) 'c
4) d'
#?
Это решение должно помочь вам:
#!/bin/bash
opts=(a b "c d");
select opt in "${opts[@]}"
do echo $opt;
break;
done
Используйте массив:
opts=("a" "b" "c d");select opt in "${opts[@]}"; do echo $opt; break; done
Ответ или решение
Чтобы использовать аргументы с пробелами в команде select
в bash, необходимо использовать массивы. Это позволит правильно обрабатывать кавычки и сохранить целостность строк, содержащих пробелы. Ниже приведено развернутое объяснение, основанное на вашем вопросе.
Проблема использования select
с аргументами, содержащими пробелы
Когда вы передаете строку с аргументами, содержащими пробелы, в команду select
, и эта строка сохранена в переменной, Bash не интерпретирует кавычки как границы аргументов. Это приводит к тому, что строка разбивается на отдельные элементы. Например, строка "c d"
будет интерпретироваться как два отдельных аргумента 'c'
и 'd'
, а не как один.
Решение проблемы с использованием массивов
Лучшим решением данной проблемы является использование массивов в bash. Массивы позволяют группировать элементы, которые могут содержать пробелы, и передавать их в команду select
корректно.
Пример использования массива с select
Ниже представлен пример скрипта, который правильно обрабатывает аргументы, содержащие пробелы:
#!/bin/bash
# Инициализация массива с элементами
opts=("a" "b" "c d")
# Использование select с массивом
select opt in "${opts[@]}"; do
echo "Вы выбрали: $opt"
break
done
В этом примере мы создаем массив opts
, в который добавляем строки с кавычками, чтобы обеспечить их целостность. С помощью конструкции ${opts[@]}
мы предоставляем команду select
аргументы в необходимом формате.
Динамическое создание массива из команды
Если вы получаете аргументы из команды, вы можете использовать следующее:
#!/bin/bash
# Команда, которая генерирует вывод с аргументами
opts_output='a b "c d"'
# Создание массива из вывода команды
# Применяем eval для корректной интерпретации кавычек
eval "opts=($opts_output)"
# Использование select с массивом
select opt in "${opts[@]}"; do
echo "Вы выбрали: $opt"
break
done
Здесь мы используем eval
, чтобы интерпретировать строку с кавычками и пробелами как массив. После этого конструкция select
работает так же, как и в предыдущем случае.
Вывод
Использование массивов в bash значительно упрощает работу с аргументами, содержащими пробелы. Это позволяет избежать подтасовок данных и обеспечивает точность выбора пользователем. Надеюсь, это поможет вам правильно работать с командой select
и аргументами, получаемыми из различных источников.