BASH字符串处理的数组的使用

简单介绍一下Bash中的数组的定义和使用方法

在Bash中,每个变量都可以作为一维数组使用,并且Bash也只支持一维数组。

$VAR等同于${VAR[0]}

还有一种多此一举的声明数组的方法:declare -a VAR

数组数据的设置方式有:

VAR=(v1 v2 v3)
VAR=([0]=v0 [1]=v1 [2]=v2)
VAR[0]=v0

引用数组元素的方式:

$VAR  ${VAR}  ${VAR[0]}  第0个元素
${VAR[n]}  第n个元素(n从0开始计算)

引用整个数组:

${VAR[*]}  ${VAR[*]}   这两种方式等同,会把数组展开。
"${VAR[*]}"  表示把数组拼接在一起的整个字符串,如果作为参数传递,会把整个字符串作为一个参数。
"${VAR[@]}"  如果作为参数传递,表示把数组中每个元素作为一个参数,数组有多少个元素,就会展开成多少个参数。

计算数组元素长度:

${#VAR[*]}  ${#VAR[@]}   不是 ${#VAR},因为它等同于 ${#VAR[0]}

注意:数组元素长度 != 最大索引 + 1,因为Bash的数组是稀疏数组(Sparse array)。

a[1]=1 
a[1000]=1000 
declare -p a 
declare -a a='([1]="1" [1000]="1000")'
echo "$a" 
echo "$a[1]" 
[1]
echo "${a[@]}" 
1 1000
echo "${#a[@]}" 
2

遍历数组元素:(注意双引号)

for ELEM in "${ARRAY[@]}"
do
    echo $ELEM
done

 以空白作为分隔符来拆分字符串构造数组

ARR=($STR)

注意$STR不能加引号。

STR="Hello World" 
ARR=($STR) 
declare -p ARR declare -a ARR='([0]="Hello" [1]="World")'

用指定分隔符来拆分字符串构造数组

如果分隔符不是空白,而是别的,那么需要借助IFS变量。

default IFS (Internal Field Separator, which is space/tab/new line)

echo $PATH 
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/apache/apache-ant-1.7.1/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
IFS=: DIRS=($PATH) 
declare -p DIRS   
declare -a DIRS='([0]="/usr/kerberos/sbin" [1]="/usr/kerberos/bin" [2]="/usr/apache/apache-ant-1.7.1/bin" [3]="/usr/local/sbin" [4]="/usr/local/bin" [5]="/sbin" [6]="/bin" [7]="/usr/sbin" [8]="/usr/bin" [9]="/root/bin")'

但是下面的方式是不行的。

echo $PATH 
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/apache/apache-ant-1.7.1/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
IFS=: declare -a DIRS=($PATH) 
declare -p DIRS 
declare -a DIRS='([0]="/usr/kerberos/sbin:/usr/kerberos/bin:/usr/apache/apache-ant-1.7.1/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin")'

 使用read -a来拆分字符串构造数组

PROVERB="All work and no play makes Jack a dull boy." 
read -a WORDS <<<$PROVERB 
echo "$WORDS"
All
echo "${#WORDS}" 
3
echo "${WORDS[*]}" 
All work and no play makes Jack a dull boy.
echo "${WORDS[@]}" 
All work and no play makes Jack a dull boy.
echo "${#WORDS[*]}" 
10
echo "${#WORDS[@]}" 
10

前面的例子中要分割的字符串是以空格分割的,现在举一个以:分割的例子。

echo $IFS 
IFS=: read -r -a DIRS <<<"$PATH" 
echo $IFS 
declare -p DIRS 
declare -a DIRS='([0]="/usr/kerberos/sbin" [1]="/usr/kerberos/bin" [2]="/usr/apache/apache-ant-1.7.1/bin" [3]="/usr/local/sbin" [4]="/usr/local/bin" [5]="/sbin" [6]="/bin" [7]="/usr/sbin" [8]="/usr/bin" [9]="/root/bin")'

下面的例子是将当前工作目录以/进行分割。

echo $PWD 
/root/work191/ct08/src/ctmw
IFS=/ read -r -a PARTS <<<$PWD 
declare -p PARTS 
declare -a PARTS='([0]=" root work191 ct08 src ctmw")'

IFS=/ read -r -a PARTS <<<"$PWD" 
declare -p PARTS                 
declare -a PARTS='([0]="" [1]="root" [2]="work191" [3]="ct08" [4]="src" [5]="ctmw")'

 使用cut命令分隔字符串

echo "$STR" | cut -f $N

以TAB分隔,打印第N个子串值,N从1开始计数。

echo "$STR" | cut -d "$DELIM" -d $N

以指定DELIM分隔,打印第N个子串值,N从1开始计数。

其中,-d部分也可以是$N1,$N2,$N3的形式,即输出多个子串。

STR="A good beginning is half done." [root@jfht ~]# echo $STR | cut -d ' ' -f 2          good
 
echo $PATH /usr/kerberos/sbin:/usr/kerberos/bin:/usr/apache/apache-ant-1.7.1/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin[root@jfht ~]# echo $PATH | cut -d ':' -f 3 /usr/apache/apache-ant-1.7.1/bin
echo $PATH | cut -d ':' -f 3,5 /usr/apache/apache-ant-1.7.1/bin:/usr/local/bin

使用awk命令分隔字符串

echo "$STR" | awk '{print $1}'
echo "$STR" | awk '{print $2}'

注意:awk后面的参数用单引号,不能用双引号。

STR="A good beginning is half done." 
echo "$STR" | awk '{print $1}' 
A
echo "$STR" | awk '{print $2}' 
good
echo "$STR" | awk '{print $5,$6}' 
half done.

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://sulao.cn/post/329

评论列表

0%