
Shell小笔记(一)
本文示例以 Bash 为准。
sh不一定指向 Bash,数组、let、字符串替换等 Bash 写法不能直接当成通用sh语法。
格式
打开文本编辑器(如vi或vim ),创建一个后缀名为sh的文件;开头第一行使用 shebang 指定解释器,如#!/bin/bash。用 ./test.sh 直接执行时,系统会据此选择解释器;用 bash test.sh 时,则由命令中指定的 Bash 解释脚本。
例如编写一个名为test.sh的脚本:
1 |
|
使用方式
bash + 脚本名运行
1 | [kaka@localhost ~]$ cat test.sh |
给执行权限后直接运行
直接运行前需要为脚本赋予执行权限(
chmod +x <脚本的文件名>)
1 | [kaka@localhost ~]$ cat test.sh |
使用 source 或 . 运行
使用
source ./a.sh或. ./a.sh,会在当前 Shell 中执行脚本。因此变量赋值、cd等操作会影响当前 Shell,也不需要给脚本执行权限。source是 Bash 支持的写法,.是 POSIX 写法。
1 | [kaka@localhost ~]$ cat a.sh |
变量
自定义变量、环境变量、位置变量、预定义变量
变量名要求
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
- 中间不能有空格,可以使用下划线
_- 不能使用标点符号
- 建议避开 Bash 保留字,也不要随意覆盖
PATH等已有变量,以免给自己整点新活如何使用
在变量名前加美元符号(
$)即可为了帮助解释器识别到变量的边界,可以在变量名外加入花括号(
{})
自定义变量
普通赋值创建的是当前 Shell 中的变量,默认不会传给子进程;它不等同于函数里的 local 局部变量。
格式:<变量名>=<变量值>,注意等号两边不需要空格
如果变量值存在空格,需要用双引号("")或单引号('')框起来
使用unset <变量名>撤销该自定义变量
环境变量
使用 export 变量名 或 export 变量名=值,可以将变量导出给之后启动的子进程。它不会自动同步到其他已打开的终端。
例如 /etc/profile 是登录 Shell 会读取的初始化文件之一,可以在其中配置环境变量;个人配置通常放在 ~/.bash_profile 等文件中,具体读取规则取决于 Shell 和启动方式。
预定义变量
下面列出的是特殊参数(包括位置参数),由 Shell 提供,不是普通的环境变量或局部变量。
| 变量 | 含义 |
|---|---|
| $n | 位置变量n为数字,$0代表该脚本名称$1代表第1个参数(以此类推),但从第十个开始要用花括号({})包含 |
| $# | 获取所有输入参数的个数 |
| $* | 使用 "$*" 时,将所有参数合成一个字符串(以 IFS 的首字符分隔) |
| $@ | 使用 "$@" 时,每个原始参数保持为独立的一项 |
| $? | 获取上一条命令的退出状态;0 通常表示成功,非零状态的具体含义由命令决定 |
创建一个名为advance.sh的文件,并写入以下内容
1 | !/bin/bash |
使用bash ./advance.sh 1 2 3 4 5命令,结果如下
1 | ==========$n========== |
💡提示:"$*" 和 "$@" 的区别需要配合双引号理解;不加引号可能再次发生单词分割和文件名展开。另外,最后的 echo $? 获取的是前一条命令的状态,不是整个脚本的状态。
只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变、不能被撤销
赋值
显示变量的值使用双引号
单引号中的
$变量名会按普通文本保留,不做变量展开反引号与
$(命令)都用于命令替换:先执行命令,再使用其标准输出,末尾的换行会被移除。嵌套时建议使用$(...)。
直接赋值
格式:<变量名>=<变量值>,注意等号两边不需要空格
1 | !/bin/bash |
键盘读取赋值
格式:read -r -p "提示信息" 变量名,可省略 -p "提示信息"
获取输入的单行数据,并赋值给变量名
1 | !/bin/bash |
通过命令行参数赋值
即通过位置变量进行调用
1 | !/bin/bash |
利用命令的输出结果赋值
在赋值语句中使用反引号,或推荐的 $(命令)。
1 | !/bin/bash |
这里的 `date +%F` 等价于 $(date +%F),可以写成 DATE=$(date +%F);直接执行 date +%F 则是输出日期,不是赋值。
从文件中读取数据赋值
这种方式适用于处理大批量的数据,直接把相应的数据写入文件中。这种方式通常是循环一行行读入数据,即每循环一次,就从文件中读入一行数据,直到文件的结尾。下面约定当前目录至少有一个 .sh 文件,且文件名不含换行。
1 | !/bin/bash |
运算符
Bash 变量默认保存文本;在
$((...))、let等算术上下文中可以做整数运算。它们不直接支持浮点数,整数除法会舍去小数部分。
基本语法
$((运算式));旧写法 $[运算式] 已不推荐使用。
1 | [kaka@localhost ~]$ a=10 |
使用expr计算
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
1 | [kaka@localhost ~]$ a=10 |
使用let计算
1 | [kaka@localhost ~]$ a=10 |
算术运算符
| 运算符 | 说明 | 举例 |
|---|---|---|
| + | 加法 | expr $a + $b |
| - | 减法 | expr $a - $b |
| * | 乘法 | expr $a \* $b 此处需要用 \转义,防止被当成文件名通配符展开 |
| / | 除法 | expr $b / $a |
| % | 取余 | expr $b % $a |
| = | 赋值 | a=$b 把变量 b 的值赋给 a |
| == | 相等 在算术条件中比较两个整数 |
(( a == b )) |
| != | 不相等 在算术条件中比较两个整数 |
(( a != b )) |
注意:使用 [ ] 测试时,两侧必须有空格,例如 [ "$a" -eq "$b" ] 比较整数,[ "$a" = "$b" ] 比较字符串。(( a == b )) 是 Bash 的算术条件写法。
替删改
替换
| 语法 | 含义 |
|---|---|
${变量名/旧模式/新字符串} |
将第一个匹配旧模式的部分替换成新字符串 |
${变量名//旧模式/新字符串} |
将全部匹配旧模式的部分替换成新字符串 |
例如将www.abca.com中的第一个a替换成d
1 | var=www.abca.com |
例如将114514中的1全部替换成9
1 | num=114514 |
删除
| 语法 | 含义 |
|---|---|
${变量名#模式} |
删除匹配模式的最短前缀 |
${变量名##模式} |
删除匹配模式的最长前缀 |
${变量名%模式} |
删除匹配模式的最短后缀 |
${变量名%%模式} |
删除匹配模式的最长后缀 |
这里的模式使用 Shell 通配符,不是正则表达式;例如 */ 匹配以 / 结尾的前缀,匹配到的 / 也会一起删除。
创建一个名为del.sh的文件,并写入以下内容
1 | file=/dir1/dir2/abc.file |
执行结果
1 | 输出名为file变量 |
默认值
使用 ${变量名-默认值}:变量未设置时使用默认值,已经设置时使用原值。这只影响展开结果,不会修改原变量。
1 | [kaka@localhost ~]$ unset num |
💡提示:${num:-1919} 会在变量未设置或为空时使用默认值;${num:=1919} 则会同时给普通变量赋值。冒号虽然小,作用可不小。








