Перенастройка списка, разделенного пробелами — размещение каждого элемента в новой строке и добавление к нему дефиса

#bash #shell #zsh

Вопрос:

У меня есть список строковых записей, разделенных пробелами

 words="foo bar baz"
 

и я хочу красиво напечатать их, каждый в новой строке, с дефисом:

 - foo
- bar
- baz
 

Как я могу этого достичь?

Я нашел много способов замены пробелов новыми строками, например

 tr ' ' 'n' <<< $words
 

но мне не повезло применить их вместе с дефисом и пробелом… по какой-то причине следующие две строки возвращают один и тот же результат:

 tr ' ' 'n' <<< $words
tr ' ' 'n- ' <<< $words
 

У меня также возникли проблемы с добавлением первого элемента, "- " не нарушая новые строки в выводе консоли.

Ответ №1:

Мог бы сделать

 words="foo bar baz";b=( $words );for i in ${!b[@]}; do echo "- ${b[$i]}";done
 

Комментарии:

1. Ну, если это массив, то просто printf "- %sn" "${b[@]}"

2. @KamilCuk Конечно. Недостаточно использовать printf, чтобы быть моим первым рефлексом. Хорошая альтернатива.

3. Ну, тогда, если использовать разделение слов, то это просто printf "- %sn" $words

Ответ №2:

sed кажется милым:

 sed 's/ /n- /g; s/^/- /' <<<"$words"
 

или:

 tr ' ' 'n' <<< $words | sed 's/^/- /'
 

Если $words простые слова разделены пробелами без каких-либо причудливых символов, подобных * ? [ подобным, вы могли бы

 printf -- "- %sn" $words
 

Обратите внимание, что расширения переменных без кавычек подвергаются разделению слов и расширению имени файла.

Комментарии:

1. Отлично работает, спасибо! Знаете ли вы, почему tr ' ' 'n- ' <<< $words и tr ' ' 'n' <<< $words возвращает один и тот же вывод?

2. tr например, сопоставляет символы 1:1 из списка. Так , например tr abc def , изменения a в d , b в e и c f в. Вызов tr ' ' 'n-' преобразует пространство в n и в основном - , и пространство не сопоставляется ни с какими входными данными, поэтому они просто игнорируются. tr это как y командование sed .

Ответ №3:

С awk :

 awk 'BEGIN {RS=" "} {print "- " $0}' <<< "${words}"
 

Ответ №4:

Это делает серия команд sed:

 sed 's/.*="//; s/"$//; s/ /n/g;' <test | sed 's/^/- /'
 

Редактировать: Упс, я думал, что words="foo baz bar" это содержимое файла…
У @KamilCuk есть гораздо более чистый способ.

Ответ №5:

Версия для zsh , основанная на некоторых других ответах и комментариях:

 printf -- '- %sn' ${=words}
 

В zsh , это может обрабатывать специальные символы, такие как подстановочные знаки:

 % words="foo? 'b'ar *bar b[a-z]"
% printf -- '- %sn' "${=words}"
- foo?
- 'b'ar
- *bar
- b[a-z]