关于Linux:在shell中,使用点作为分隔符拆分字符串的一部分

 2019-05-06 

In shell, split a portion of a string with dot as delimiter

本问题已经有最佳答案,请猛点这里访问。

我是一个新的外壳脚本,请您帮助以下要求,谢谢。

1
2
3
4
5
6
7
$AU_NAME=AU_MSM3-3.7-00.01.02.03
#separate the string after last"-", with"." as delimiter
#that is, separate"00.01.02.03" and print/save as below.
major=00
minor=01
micro=02
build=03

首先,请注意,在分配给shell中的参数时,不使用$。你的第一行应该是:

1
AU_NAME=AU_MSM3-3.7-00.01.02.03

一旦你有了它,你就可以这样做:

1
2
3
IFS=. read major minor micro build <<EOF
${AU_NAME##*-}
EOF

其中,##*-从字符串的开头到最后一个"-"剥离所有内容,只留下"00.01.02.03",ifs(内部字段分隔符)变量告诉shell在哪里将字符串拆分为字段。

在bash、zsh和ksh93+中,通过将here文档缩短为here字符串,可以将其放到一行上:

1
IFS=. read major minor micro build <<<"${AU_NAME##*-}"

更一般地说,在那些相同的shell(或任何其他具有数组的shell)中,可以拆分为任意大小的数组,而不是不同的变量。这在给定的shell中有效:

1
IFS=. components=(${AU_NAME##*-})

在旧版的ksh中,您可以这样做:

1
IFS=. set -A components ${AU_NAME##*-}

这就得到了这种等价性(zsh中除外,zsh默认为元素1-4而不是0-3):

1
2
3
4
major=${components[0]}
minor=${components[1]}
micro=${components[2]}
build=${components[3]}

bash中,您可以这样做:

1
2
3
4
5
version=$(echo $AU_NAME | grep -o '[^-]*$')
major=$(echo $version | cut -d. -f1)
minor=$(echo $version | cut -d. -f2)
micro=$(echo $version | cut -d. -f3)
build=$(echo $version | cut -d. -f4)

grep调用使用-o只输出行的匹配部分。匹配本身是行尾的每个非连字符。

cut命令使用delimeter .(-d.),并使用-f选择单个字段。

有点笨重。我肯定有更好的方法来实现这一点,但是你可以单独用grepcut做很多事情,所以它们是你的武器库中的便利工具。


您可以使用参数扩展和特殊的IFS变量。

1
2
3
4
5
6
7
8
9
10
11
#! /bin/bash
AU_NAME=AU_MSM3-3.7-00.01.02.03
IFS=. VER=(${AU_NAME##*-})
for i in {0..3} ; do
    echo ${VER[i]}
done

major=${VER[0]}
minor=${VER[1]}
micro=${VER[2]}
build=${VER[3]}

顺便说一句,在赋值中,不要用美元符号在左边开始变量。