Bash 和 IFS:字符串拆分为具有特定分隔符的数组添加一个额外的空元素
Bash and IFS: string split to an array with specific separator add an extra empty element
关于将字符串拆分成数组我们有两种场景:
如果字符串中有空spaces怎么分隔符,按照下面的post:
- Reading a space-delimited string into an array in Bash
所以如果我使用:
string="Hello Unix World"
array1=($string)
echo ${array1[@]}
echo "size: '${#array1[@]}'"
read -a array2 <<< $string
echo ${array2[@]}
echo "size: '${#array2[@]}'"
输出为:
Hello Unix World
size: '3'
Hello Unix World
size: '3'
两种方法都按预期工作。
现在,如果字符串有不同于空的东西 space 如何分隔符,根据以下 post:
- How to split a string into an array in Bash?
所以如果我使用:
path="/home/human/scripts"
IFS='/' read -r -a array <<< "$path"
echo "Approach 1"
echo ${array[@]}
echo "size: '${#array[@]}'"
echo "Approach 2"
for i in "${array[@]}"; do
echo "$i"
done
echo "Approach 3"
for (( i=0; i < ${#array[@]}; ++i )); do
echo "$i: ${array[$i]}"
done
它打印:
Approach 1
home human scripts <--- apparently all is ok, but see the line just below!
size: '4'
Approach 2
<--- an empty element
home
human
scripts
Approach 3
0: <--- confirmed, the empty element
1: home
2: human
3: scripts
为什么会出现那个空元素?如何修复命令以避免这种情况?
您的字符串分为 4 个部分:一个空部分和三个单词。
path="/home/human/scripts"
IFS='/' read -r -a array <<< "$path"
declare -p array
输出:
declare -a array=([0]="" [1]="home" [2]="human" [3]="scripts")
有很多方法可以修复它。一种是删除空值。另一种是在拆分之前排除开头的斜线。
for i in "${!array[@]}"; do
[[ ${array[i]} ]] || unset 'array[i]'
done
或者
IFS='/' read -r -a array <<< "${path#/}"
第一个适用于路径形式,斜杠不仅在开头重复。
只是为了补充真正格式化的评论:
手册(在 3.5.7 Word Splitting 中)将 IFS 描述为“字段 终止符”:
The shell treats each character of $IFS
as a delimiter, and splits the results of the other expansions into words using these characters as field terminators.
对于IFS=/ read -a fields <<< "/home/user"
,第一个字段是以第一个斜杠结尾的空字符串。
关于将字符串拆分成数组我们有两种场景:
如果字符串中有空spaces怎么分隔符,按照下面的post:
- Reading a space-delimited string into an array in Bash
所以如果我使用:
string="Hello Unix World"
array1=($string)
echo ${array1[@]}
echo "size: '${#array1[@]}'"
read -a array2 <<< $string
echo ${array2[@]}
echo "size: '${#array2[@]}'"
输出为:
Hello Unix World
size: '3'
Hello Unix World
size: '3'
两种方法都按预期工作。
现在,如果字符串有不同于空的东西 space 如何分隔符,根据以下 post:
- How to split a string into an array in Bash?
所以如果我使用:
path="/home/human/scripts"
IFS='/' read -r -a array <<< "$path"
echo "Approach 1"
echo ${array[@]}
echo "size: '${#array[@]}'"
echo "Approach 2"
for i in "${array[@]}"; do
echo "$i"
done
echo "Approach 3"
for (( i=0; i < ${#array[@]}; ++i )); do
echo "$i: ${array[$i]}"
done
它打印:
Approach 1
home human scripts <--- apparently all is ok, but see the line just below!
size: '4'
Approach 2
<--- an empty element
home
human
scripts
Approach 3
0: <--- confirmed, the empty element
1: home
2: human
3: scripts
为什么会出现那个空元素?如何修复命令以避免这种情况?
您的字符串分为 4 个部分:一个空部分和三个单词。
path="/home/human/scripts"
IFS='/' read -r -a array <<< "$path"
declare -p array
输出:
declare -a array=([0]="" [1]="home" [2]="human" [3]="scripts")
有很多方法可以修复它。一种是删除空值。另一种是在拆分之前排除开头的斜线。
for i in "${!array[@]}"; do
[[ ${array[i]} ]] || unset 'array[i]'
done
或者
IFS='/' read -r -a array <<< "${path#/}"
第一个适用于路径形式,斜杠不仅在开头重复。
只是为了补充真正格式化的评论:
手册(在 3.5.7 Word Splitting 中)将 IFS 描述为“字段 终止符”:
The shell treats each character of
$IFS
as a delimiter, and splits the results of the other expansions into words using these characters as field terminators.
对于IFS=/ read -a fields <<< "/home/user"
,第一个字段是以第一个斜杠结尾的空字符串。