定义变量
和 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"。