Ответ 1
# REVISION: 2017-03-14
# Use of read and other bash specific features (bashisms)
Поскольку скобки используются для выделения массива , а не строки :
ids="1 2 3 4";echo ${ids// /|}
1|2|3|4
Некоторые примеры: заполнение $ids
двумя строками: a b
и c d
ids=("a b" "c d")
echo ${ids[*]// /|}
a|b c|d
IFS='|';echo "${ids[*]}";IFS=$' \t\n'
a b|c d
... и, наконец:
IFS='|';echo "${ids[*]// /|}";IFS=$' \t\n'
a|b|c|d
Когда массив собран, разделяется 1-м char из $IFS
, но с пробелом заменяется на |
в каждом элементе массива.
Когда вы выполните:
id="${ids[@]}"
вы передаете строковое построение из слияния массива ids
пробелом в новую переменную типа string.
Примечание:, когда "${ids[@]}"
дает строку, разделенную пробелом, "${ids[*]}"
(со звездой *
вместо знака at @
) будет отображать строку, разделенную символом первый символ $IFS
.
что man bash
говорит:
man -Len -Pcol\ -b bash | sed -ne '/^ *IFS /{N;N;p;q}'
IFS The Internal Field Separator that is used for word splitting
after expansion and to split lines into words with the read
builtin command. The default value is ``<space><tab><newline>''.
Игра с $IFS
:
set | grep ^IFS=
IFS=$' \t\n'
declare -p IFS
declare -- IFS="
"
printf "%q\n" "$IFS"
$' \t\n'
Буквально a space
, a tabulation
и (значение or) a line-feed
. Итак, в то время как первый символ - это пробел. использование *
будет делать то же самое, что и @
.
Но
{
# OIFS="$IFS"
# IFS=$': \t\n'
# unset array
# declare -a array=($(echo root:x:0:0:root:/root:/bin/bash))
IFS=: read -a array < <(echo root:x:0:0:root:/root:/bin/bash)
echo 1 "${array[@]}"
echo 2 "${array[*]}"
OIFS="$IFS" IFS=:
echo 3 "${array[@]}"
echo 4 "${array[*]}"
IFS="$OIFS"
}
1 root x 0 0 root /root /bin/bash
2 root x 0 0 root /root /bin/bash
3 root x 0 0 root /root /bin/bash
4 root:x:0:0:root:/root:/bin/bash
Примечание. Линия IFS=: read -a array < <(...)
будет использовать :
в качестве разделителя без постоянной установки $IFS
. Это потому, что выходная строка #2
содержит пробелы в качестве разделителей.