bash数组与字典总结
一. 数组
bash 里面也有数组和字典,数组分为索引数组和关联数组(关联数组也就是在其他语言里面的字典,数组和字典的操作方式基本一致)。
declare -p 可以查询变量的属性名称和值,下面创建了一个 names 数组,然后查看数组的值。
yzy@cs:~$ declare -a names=("a" "b" "c" "d")
yzy@cs:~$ declare -p names
declare -a names=([0]="a" [1]="b" [2]="c" [3]="d")
1.1 创建数组
# 创建空数组:两种方式
names=()
declare -a names=()
# 创建数组同时赋值:两种方式
names=("a" "b" "c")
declare -a names=("a" "b" "c" "d")
# 在末尾添加元素
names=("a")
names+=("beijing" "shanghai" "guangzhou")
# 多个数组合并为一个数组
ages=(19 20 99)
names=(beijing shanghai)
ages_names=(${ages[@]} ${names[@]})
# 引用变量
names=("a" "b" "c" "$USER")
# 指定路径加通配符
files=(*)
photos=(~/"My Photos"/*.jpg)
# 通过指定索引号定义数组
names2[0]="Bob"
names2[4]="Bob4"
# 指定索引号,索引号不连续的也叫稀疏数组
names=([0]="Bob" [1]="Peter" [20]="$USER" [21]="Big Bad John")
# 精确匹配: 搜索数组里面的元素,如果元素包含了 shang,则替换成 sang
names=(beijing shanghai shangtian)
new_names=(${names[@]/shang/sang})
# 模糊匹配: 搜索数组里面的元素,如果元素以 shang 开头,则替换成 guizhou
names=(beijing shanghai shangtian)
new_names=(${names[@]/shang*/guizhou})
1.2 访问数组
# 数组下标访问
yzy@cs:~$ char=(a b c q w x y z)
yzy@cs:~$ echo "${char[2]}"
c
# 分片访问
# 表示从下标为 3 的位置开始访问 2 个元素
yzy@cs:~$ arr=(able good fly python java test go now)
yzy@cs:~$ echo "${arr[@]:3:2}"
python java
# 元素个数
yzy@cs:~$ arr=(a b c)
yzy@cs:~$ echo ${#arr[@]}
3
# 元素个数
yzy@cs:~$ myfiles=([0]=".bashrc" [1]="codes.xlsx" [4]="hello.c")
yzy@cs:~$ echo ${#myfiles[@]}
3
# 指定下标的元素值的字符个数
yzy@cs:~$ arr=(able good fly python java test go now)
yzy@cs:~$ echo "${#arr[3]}"
6
1.3 遍历数组
# 打印出变量的类型和值
yzy@cs:~$ myfiles=(/*)
yzy@cs:~$ declare -p myfiles
# 打印值
yzy@cs:~$ names=("Bob" "Peter" "$USER" "BigJohn")
yzy@cs:~$ printf '%s\n' "${names[@]}"
Bob
Peter
yzy
BigJohn
# 打印值
yzy@cs:~$ names=("Bob" "Peter" "$USER" "BigJohn")
yzy@cs:~$ echo "users: ${names[*]}"
users: Bob Peter yzy BigJohn
# 拷贝多个文件
myfiles=(db.sql home.bz2 etc.bz2)
cp "${myfiles[@]}" /backups/
# for 循环:获取元素
for file in "${myfiles[@]}"; do
echo "$file"
done
# for 循环:获取索引
for i in "${!myfiles[@]}"; do
echo "$i -> ${myfiles[i]}"
done
# 遍历数组下标,但是步长为2
mychars=(a b c q w x y z)
for ((i=0; i<${#mychars[@]}; i+=2)); do
echo "${mychars[i]} and ${mychars[i+1]}"
done
# 结果
a and b
c and q
w and x
y and z
1.4 删除元素
删除指定下标的元素
yzy@cs:~$ mychars=(a b c q w)
yzy@cs:~$ declare -p mychars
declare -a mychars=([0]="a" [1]="b" [2]="c" [3]="q" [4]="w")
yzy@cs:~$ unset mychars[2]
yzy@cs:~$ declare -p mychars
declare -a mychars=([0]="a" [1]="b" [3]="q" [4]="w")
二. 字典
bash里面的字典叫做关联数组,字典其实和数组类似,不同点在于,字典的key是字符串,并且遍历时是随机的。
注意事项:
- 字典的key遍历是随机的顺序, 它不适合存放顺序的元素
- 除了遍历是随机的外, 字典的用法基本和数组是一致的
2.1 创建字典
一定要显示定义
# 方法1
yzy@cs:~$ declare -A ages
yzy@cs:~$ ages=(["wang"]=21 ["zhang"]=18)
yzy@cs:~$ echo "my age is ${ages[wang]}"
my age is 21
# 方法2
yzy@cs:~$ declare -A names
yzy@cs:~$ names["wang"]="wang xiao"
yzy@cs:~$ names["zhang"]="zhang xiao"
yzy@cs:~$ declare -p names
declare -A names=([zhang]="zhang xiao" [wang]="wang xiao" )
2.2 遍历字典
像遍历数组一样,只不过 index 变成字符串了
declare -A ages
ages=(["wang"]=21 ["zhang"]=18)
for name in "${!ages[@]}"; do
echo "name: $name, age: ${ages[$name]}."
done
# 结果
name: zhang, age: 18.
name: wang, age: 21.
三. 总结
一句话总结:
for value in "${myfiles[@]}"
表示遍历数组的元素值for index in "${!myfiles[@]}"
表示遍历数组的下标号echo "${#myfiles[@]}"
表示获取数组的元素个数echo "${names[*]}"
表示一次性的打印成字符串便于阅读declare -a variable
表示定义一个数组declare -A variable
表示定义一个字典declare -p variable
表示打印遍历variable的类型、值