shell中对变量的操作

声明变量

声明变量通常使用 declare 命令来操作

1
2
3
4
5
6
$ declare [OPTIONS] VARIABLES
-i # 整型
-a # 数值
-x # 环境变量
-r # 只读变量,不能撤销,不能修改,相当于readonly
-f # 声明函数

不使用 declare ,直接使用等号也没有任何问题

1
2
declare -i A=20
b=30

变量赋值

变量赋值的时候,等号两边不能有空格,如果值里面包括空格必须用引号,variable="hello world"

1
2
3
4
5
var_name =VALUE # 这里的变量为本地变量
declare -i var_name=VALUE # 定义为整型
declare -x var_name=VALUE # 定义为环境变量
declare -r var_name=VALUE 或 readonly var_name=VALUE
# 只读变量只有进程结果后才会撤销,若定义在环境配置文件中则需要手动清除

变量引用

变量的引用实际就是将变量名替换为变量所指向的数据。

1
2
3
4
5
[user1@study ~]$ a=123;echo $a
123
[user1@study ~]$ b=456;echo ${b}
456
[user1@study ~]$

变量撤销

使用 $ 可以对变量进行引用,在撤销变量的时候不需要 $ 直接使用变量名即可

1
2
3
4
5
6
[user1@study ~]$ a='Tom';b='Jerry';echo $a and $b
Tom and Jerry
[user1@study ~]$ unset a b
[user1@study ~]$ echo $a and $b
and
[user1@study ~]$

变量间接引用

当一个变量所指向的数据是另外一个变量的名字时,可以间接性的引用那个变量所对应的数据。通常使用 ${!var_name} 的方式来实现

1
2
3
4
5
6
[user1@study ~]$ message=hello
[user1@study ~]$ hello=goodbye
[user1@study ~]$ echo $message
hello
[user1@study ~]$ echo ${!message}
goodbye

使用转义符 \$ 转义而后交给 eval 命令也能实现变量的间接引用

1
2
3
4
5
6
7
[user1@study ~]$ message=hello;hello=goodbye
[user1@study ~]$ echo $message
hello
[user1@study ~]$ eval x=\$$message
[user1@study ~]$ echo ${x}
goodbye
[user1@study ~]$

变量的查看

1
2
3
4
5
6
set # 显示(设置)所有 shell 变量(包括环境变量及本地变量)
env # 显示(设置)当 前shell 的环境变量
printenv # 同 env
export # 显示(设置)导出成当前 shell 环境变量的变量。
declare -x # 同 export
declare -r # 显示只读变量

示例

1
2
3
4
5
6
7
8
9
10
[user1@study ~]$ name='Tom';echo ${name}  # shell 本地变量设定及其引用
Tom
[user1@study ~]$ env | grep name # 当前 shell 的环境变量不存在
[user1@study ~]$ set | grep name # 本地变量存在
name=Tom
[user1@study ~]$ export | grep name # 导出成当前 shell 的环境变量也不存在
[user1@study ~]$ export name # 使用 export 导出为当前shell的环境变量
[user1@study ~]$ env | grep name
name=Tom
[user1@study ~]$

从变量提取字符串

假设定义了变量 strings

1
2
3
4
[user1@study ~]$ strings=hello.10.10.10.10.test.world
[user1@study ~]$ echo ${strings}
hello.10.10.10.10.test.world
[user1@study ~]$

${strings#*10} 删除掉第一个 10 和它左边的字符串

1
2
3
[user1@study ~]$ echo ${strings#*10}
.10.10.10.test.world
[user1@study ~]$

${strings##*10} 删除掉最后一个 10 和它左边的字符串

1
2
3
[user1@study ~]$ echo ${strings##*10}
.test.world
[user1@study ~]$

${strings%10*} 删除掉最后一个 10 和它右边的字符串

1
2
3
[user1@study ~]$ echo ${strings%10*} 
hello.10.10.10.
[user1@study ~]$

${strings%%10*} 删除掉第一个 10 和它右边的字符串

1
2
3
[user1@study ~]$ echo ${strings%%10*}
hello.
[user1@study ~]$

看上去有些绕,为了便于记忆,可以用键盘上的 $ 做个分隔。键盘上 # 位于 $ 的左边,所以提取字符串的时候向左删除,% 位于 $ 的右边,所以提取字符串的时候向右删除。

这里用到的 * 只是一个通配符,有的时候可以不要。单一符号最小匹配,两个符号最大匹配,匹配到的内容删掉。

基于字符串切片

从变量指向的字符串中按照指定长度切取数据

  • ${var:offset:length}
    • offset:要跳过字节的个数;
    • length:取出字节的长度,如果省略则取偏移量后所有元素
  • ${var: -length}

操作示例

1
2
3
4
5
6
7
8
9
10
11
12
[user1@study ~]$ mypath="/etc/sysconfig/network-scripts/"
[user1@study ~]$ echo ${mypath:5} # 提取最左边的 5 个字节右边的内容
sysconfig/network-scripts/
[user1@study ~]$ echo ${mypath:10} # 提取第 10 个字节右边的内容
nfig/network-scripts/
[user1@study ~]$ echo ${mypath:4:10} # 提取第 4 个字节右边的 10 个字节长度的内容
/sysconfig
[user1@study ~]$ echo ${mypath: -10} # 取出字符串最后10个字节,- 前面需要有空格
k-scripts/
[user1@study ~]$ echo ${#mypath} # 取出字符长度
31
[user1@study ~]$

大小写切换

${a^^}$a 中所有小写字母替换为大写

1
2
3
[user1@study ~]$ a='Tom and Jerry';echo ${a^^}
TOM AND JERRY
[user1@study ~]$

${a,,} 把$a` 中所有大写字母替换为小写

1
2
3
[user1@study ~]$ a='Tom and Jerry';echo ${a,,}
tom and jerry
[user1@study ~]$

变量展开

1
2
3
4
5
6
7
8
${a=hehe}   # 若 $a 未设定,则用 hehe 作传回值,同时将 $a 赋值为 hehe (空及非空时不作处理)
${a:=hehe} # 若 $a 未设定或为空,则使用hehe作传回值,同时将 $a 赋值为hehe (非空时不作处理)
${a-hehe} # 若 $a 未设定,则使用 hehe 作传回值(空及非空时不作处理)
${a:-hehe} # 若 $a 未设定或为空,则使用hehe 作传回值(非空时不作处理)
${a+hehe} # 若 $a 设为空或非空,则使用hehe作传回值(未设定时不作处理)
${a:+hehe} # 若 $a 为非空,则使用 hehe 作传回值(未设定及空时不作处理)
${a?hehe} # 若 $a 未设定,则将 hehe 输出至STDERR(空及非空时不作处理)
${a:?hehe} # 若 $a 未设定或为空,则将 hehe 输出至 STDERR(非空时不作处理)

以上的理解在于,要分清楚 unset 与 null 及 non-null 这三种赋值状态。

其中 :null 有关,如果不带 :null 不受影响;如果带了 : 则连 null 也受影响。

字符串的替换(globbing)

1
2
3
4
${a/hehe/haha}   # 将变量 a 中第一个 hehe 提换为 haha
${a//hehe/haha} # 将变量 a 中全部 hehe 提换为 haha
${string/#substring/replace} # 若 $strting 最前面匹配substring,就用replace来替换substring
${string/%substring/replace} # 若 $strting 最后面匹配substring,就用replace来替换substring

字符串的删除(globbing)

1
2
3
4
${a/hehe}    # 查找 $a 中首次匹配到的字符串hehe,并删除之
${a//hehe} # 查找 $a 中所有匹配到的字符串hehe,并删除之
${a/#hehe} # 查找 $a 中首部匹配到的字符串hehe,并删除之
${a/%hehe} # 查找 $a 中尾部到的字符串hehe,并删除之
有钱任性,请我吃包辣条
0%