在
bash中,我想将可能包含空格分隔元素的类似PATH的环境变量转换为数组,确保带空格的元素不会导致分词,显示为“多个元素”.
让PATH_VARIABLE成为有问题的变量.
让un:dodecaedro:per:tirare:per:i danni是变量的内容.
它适用于所需的数组_有6个元素,而不是7个元素.
0) un 1) dodecaedro 2) per 3) tirare 4) per 5) i danni
“棘手”的条目可能是以空格分隔的值:i danni.
我正在寻找绝对最优雅和正确的方法来实现这一目标.
限制:它必须适用于我的bash版本:v3.2.48(1) – 发布
在python,这样做非常精美:
>>> v='un:dodecaedro:per:tirare:per:i danni' >>> len(v.split(':')) 6
作品.显示我在寻找什么.
你能否专门改进我的尝试4?
在这里我的尝试
#!/bin/bash PATH_VARIABLE='un:dodecaedro:per:tirare:per:i danni' # WRONG a1=($(echo $PATH_VARIABLE | tr ':' '\n')) # WRONG a2=($( while read path_component; do echo "$path_component" done < <(echo "$PATH_VARIABLE" | tr ':' '\n') )) # WORKS,it is elegant.. but I have no bash 4! # readarray -t a3 < <(echo "$PATH_VARIABLE" | tr ':' '\n') # WORKS,but it looks "clunky" to me :( i=0 while read line; do a4[i++]=$line done < <(echo "$PATH_VARIABLE" | tr ':' '\n') n=${#a4[@]} for ((i=0; i < n; i++)); do printf '%2d) %s\n' "$i" "${a4[i]}" done
我的环境
bash v3.2.48(1) – 发布
osx OS X v10.8.3(build 12D78)
f() { local IFS=: local foo set -f # Disable glob expansion foo=( $@ ) # Deliberately unquoted set +f printf '%d\n' "${#foo[@]}" printf '%s\n' "${foo[@]}" } f 'un:dodecaedro:per:tirare:per:i danni' 6 un dodecaedro per tirare per i danni
修改Jim McNamara的答案,你可以重置IFS:
oIFS="$IFS" foo='un:dodecaedro:per:tirare:per:i danni' IFS=: arr=( $foo ) IFS="$oIFS"
我更喜欢功能范围,因为它可以保护IFS更改不会流失到全局范围,而无需特别注意重置它.
编辑和解释:
作为澄清:在第二个示例中,IFS设置确实更改了全局变量.这个之间的显着差异:
IFS=: arr=( $foo )
和这个:
IFS=: read -a arr <<< "$foo"
是前者是两个变量赋值而没有命令,后者是一个简单的命令(参见man(1)bash中的简单命令.)
示范:
$echo "$BASH_VERSION" 3.2.48(1)-release $echo "$IFS" $foo='un:dodecaedro:per:tirare:per:i danni' $IFS=: read -a arr <<< "$foo" $echo "${#arr[@]}" 6 $echo "$IFS" $IFS=: arr1=( $foo ) $echo "${#arr1[@]}" 6 $echo "$IFS" :