定义变量
和 C/C++ 一样,shell 也有变量,并且定义方式大同小异。
如:name=Otokaze
、name='Otokaze'
、name="Otokaze"
;
三种方式都可以,并且不需要指明变量类型,因为它们本质都是字符串。
但是,如果变量值存在空白符(如:空格),则必须使用引号包围起来。
单引号和双引号是有区别的,具体细节在后文有说明:单双引号区别。
给 shell 变量定义、赋值、初始化时,
=
两边不能有空格等空白字符。
从标准输入读取
除了普通的变量定义方式,我们也可以获取用户的输入,并将其存储在变量中;
语法:read var_name
,当运行到read
所在行时,当前 shell 进程阻塞,等待用户输入;
当用户输入完成,并键入回车后,当前进程继续执行,输入的字符串(不包含换行符)将保存至var_name
中。
变量命名规则
只能以字母
或_
开头,后面可跟字母
、数字
、_
。
变量初始化
在定义变量的时候必须进行赋值(称为:初始化),如 name='Otokaze'
,也可以赋空值:name=""
;
shell 允许你直接使用未定义/赋值的变量,未定义变量在字符串上下文中为空串,数值上下文中为 0。
引用变量值
定义变量后就可以使用这个变量了,比如我要打印 name 变量的值:echo ${name}
或echo $name
。
注意,在引用变量时,必须加上$
,并且最好加上{}
来标识边界,这是一个很好的编程习惯!
假设name=123
,则${name}s
扩展为123s
;而$names
扩展为空串,因为我们未定义names
变量。
重新赋值
一个变量被定义后,可以被重新赋值,变量名前不用加$
。如:name="Google"
。
可以这样简单记忆:
- 定义/写入 变量值时,不带
$
- 引用/读取 变量值时,带上
$
只读变量
有时候我们想定义一个常量,或者叫只读变量;
在 C/C++ 中使用关键字const
,在 shell 中使用readonly
。
readonly MAX_SIZE=100
,直接定义;MAX_SIZE=100; readonly MAX_SIZE
,将变量设置为只读。
任何尝试修改或删除只读变量的操作都会产生 MAX_SIZE: readonly variable
错误。
删除变量
使用unset
命令,可以一次性删除多个变量。
如:unset name
、unset var_a var_b var_c
。
只读变量不可以用 unset 删除,它的生命周期和 shell 进程一样长。
变量作用域
局部变量:在函数中使用
local
关键字定义的变量是局部变量。局部变量只能在 函数上下文 使用;local 变量在函数被调用时初始化,在函数返回时被自动释放。全局变量:未使用
local
关键字定义的变量都是全局变量。全局变量在 shell 进程结束时、执行unset
时,才会被释放。如非必要,请避免创建全局变量,尽量使用 local。环境变量:使用
export 变量名
可以将全局变量导出为环境变量,使用export -n 变量名
撤销导出。环境变量可以使用env
命令查看,子进程会继承(拷贝)父进程的环境变量。
单双引号区别
单引号的特点:
- 单引号中的任何字符都会原样输出,比如 变量引用
${}
、命令替换$()
都不会执行,原样输出; - 单引号字符串中不允许出现单引号,就算是使用反斜杠转义也不行,也就是说单引号必须成对出现!
双引号的特点:
- 可以进行 变量引用
${}
、命令替换$()
等操作; - 允许转义字符,可以包含单引号(无需转义),可以包含双引号(需要转义)。
无论是单引号还是双引号,它们都可以用来存储多行字符串(也就是字符串可以跨行)。
获取字符串长度
使用#
号,如:url="www.zfl9.com"
,则 echo ${#url}
输出 12。
提取子串
索引值从 0 开始,支持负数索引,从-1
开始(需要加前导0
,见下):
echo ${url:3:5}
,输出".zfl9"
,3 表示从索引 3 开始,5 表示提取 5 个字符;echo ${url:0-8:4}
,输出"zfl9"
,0-8 表示从索引 -8 开始,4 表示提取 4 个字符;echo ${url:3}
,输出".zfl9.com"
,如果省略长度,则默认提取后面的所有字符;echo ${url:0-1}
,输出"m"
,因为没有指定长度,所以默认提取后面的所有字符。
删除子串
操作符:
#
或##
操作符:从字符串 左边 匹配子串,然后删除;%
或%%
操作符:从字符串 右边 匹配子串,然后删除。
匹配模式:
- 可使用 glob 通配符,如
?
、*
、[]
、[^]
; #
和%
操作符中的*
为最短匹配(非贪婪);##
和%%
操作符中的*
为最长匹配(贪婪)。
最短匹配:
echo ${url#w*.}
,最短匹配(左),输出"zfl9.com"
;echo ${url%.*}
,最短匹配(右),输出"www.zfl9"
;
最长匹配:
echo ${url##w*.}
,最长匹配(左),输出"com"
;echo ${url%%.*}
,最长匹配(右),输出"www"
。
替换子串
echo ${url/./*}
,仅替换一次,输出"www*zfl9.com"
;echo ${url//./*}
,替换所有匹配的子串,输出"www*zfl9*com"
。