Pet*_*r.O 11 shell scripting bash
使用具有非空白空间值的 IFS 解析数组会创建空元素。
即使使用tr -s
将多个 delim 缩小为单个 delim 也是不够的。
一个例子可以更清楚地解释这个问题..
有没有办法通过调整 IFS 来实现“正常”结果(是否有相关的设置来改变 IFS 的行为?.... 即与默认空格相同国际金融服务公司。
var=" abc def ghi "
echo "============== IFS=<default>"
arr=($var)
for x in ${!arr[*]} ; do
echo "# arr[$x] \"${arr[x]}\""
done
#
sfi="$IFS" ; IFS=':'
set -f # Disable file name generation (globbing)
# (This data won't "glob", but unless globbing
# is actually needed, turn if off, because
# unusual/unexpected combinations of data can glob!
# and they can do it in the most obscure ways...
# With IFS, "you're not in Kansas any more! :)
var=":abc::def:::ghi::::"
echo "============== IFS=$IFS"
arr=($var)
for x in ${!arr[*]} ; do
echo "# arr[$x] \"${arr[x]}\""
done
echo "============== IFS=$IFS and tr"
arr=($(echo -n "$var"|tr -s "$IFS"))
for x in ${!arr[*]} ; do
echo "# arr[$x] \"${arr[x]}\""
done
set +f # enable globbing
IFS="$sfi" # re-instate original IFS val
echo "============== IFS=<default>"
Run Code Online (Sandbox Code Playgroud)
这是输出
============== IFS=<default>
# arr[0] "abc"
# arr[1] "def"
# arr[2] "ghi"
============== IFS=:
# arr[0] ""
# arr[1] "abc"
# arr[2] ""
# arr[3] "def"
# arr[4] ""
# arr[5] ""
# arr[6] "ghi"
# arr[7] ""
# arr[8] ""
# arr[9] ""
============== IFS=: and tr
# arr[0] ""
# arr[1] "abc"
# arr[2] "def"
# arr[3] "ghi"
============== IFS=<default>
Run Code Online (Sandbox Code Playgroud)
从bash
联机帮助页:
IFS 中非 IFS 空格的任何字符,以及任何相邻的 IFS 空格字符,都用于分隔字段。一系列 IFS 空白字符也被视为分隔符。
这意味着IFS 空格(空格、制表符和换行符)不会像其他分隔符那样处理。如果您想使用替代分隔符获得完全相同的行为,您可以在tr
or的帮助下进行一些分隔符交换sed
:
var=":abc::def:::ghi::::"
arr=($(echo -n $var | sed 's/ /%#%#%#%#%/g;s/:/ /g'))
for x in ${!arr[*]} ; do
el=$(echo -n $arr | sed 's/%#%#%#%#%/ /g')
echo "# arr[$x] \"$el\""
done
Run Code Online (Sandbox Code Playgroud)
这个%#%#%#%#%
东西是一个神奇的值来替换字段内可能的空间,它应该是“唯一的”(或非常无链接)。如果您确定字段中不会有任何空间,请删除此部分)。
小智 4
要删除多个(非空格)连续分隔符,可以使用两个(字符串/数组)参数扩展。技巧是将IFS
变量设置为空字符串以进行数组参数扩展。
这记录在分词man bash
下:
由于扩展没有值的参数而产生的不带引号的隐式空参数将被删除。
(
set -f
str=':abc::def:::ghi::::'
IFS=':'
arr=(${str})
IFS=""
arr=(${arr[@]})
echo ${!arr[*]}
for ((i=0; i < ${#arr[@]}; i++)); do
echo "${i}: '${arr[${i}]}'"
done
)
Run Code Online (Sandbox Code Playgroud)