Проблема заключалась в том, что по умолчанию echo
добавляет новую строку при каждом вызове и sed
работал на этих новых линиях. Вы не могли этого увидеть, потому что, когда bash обрабатывает $ (...)
, эти новые строки преобразуются в пробелы. Итак, чтобы исправить проблему, внося минимальные изменения в ваш подход:
$ x=$(for i in a b c; do echo -n "${i}",; done| sed 's/,$//') ; echo $x
a,b,c
Параметр -n
указывает echo
не добавлять новые строки.
Если вам нужны пробелы между элементами, их легко добавить:
$ x=$(for i in a b c; do echo -n "${i}, " ; done| sed 's/, $//') ;echo $x
a, b, c
Оператор select
в bash
, который отображает меню, не позволяет указать отступ для меню.
Просто комментарий к коду. :Обычно проще позволить оператору case
воздействовать на $REPLY
, а не на переменную с выбранной строкой. Это избавляет вас от необходимости вводить строки дважды.
.
select opt in "${options[@]}"
do
case $REPLY in
1)
echo "Your choice is 1"
;;
2)
echo "Your choice is 2"
;;
3)
break
;;
*) echo 'Invalid option' >&2
esac
done
или, для этого конкретного примера,
select opt in "${options[@]}"
do
case $REPLY in
[1-2])
printf 'Your choice is %s\n' "$REPLY"
;;
3)
break
;;
*) echo 'Invalid option' >&2
esac
done
Не так уж сложно (грубо )заново реализовать select
вручную и точно -настроить отображение, по крайней мере, пока у вас не так много опций, чтобы нуждаться в нескольких столбцах -листинг.
#!/bin/bash
# print the prompt from $1, and a menu of the other arguments
choose() {
local prompt=$1
shift
local i=0
for opt in "$@"; do
# we have to do the numbering manually...
printf " %2d) %s\n" "$((i += 1))" "$opt"
done
read -p "$prompt: "
}
options=("Foo" "Bar" "Quit")
while choose 'Please enter your choice' "${options[@]}"; do
case $REPLY in
1) echo "you chose 'foo'" ;;
2) echo "you chose 'bar'";;
3) echo 'you chose to quit'; break;;
*) echo 'invalid choice';;
esac
done
Конечно, это можно было бы расширить, чтобы принять во внимание ключи массива (индексы )и представить их в качестве вариантов выбора в меню вместо текущего счетчика.