学习 shell 内容!
- 前言
- 一、作用
- 二、变量
- 1. 定义
- 2. 注释
- 3. 取变量中的值
- 4. 只读变量
- 5. 删除变量
- 6. 字符串
- 三、默认变量
- 四、数组
- 1. 定义
- 2. 取数组中元素的值
- 3. 读取整个数组
- 4. 取数组长度
- 五、expr
- 六、read
- 七、echo
- 八、printf
- 九、test 与 [ ]
- && 和 ||
- test 命令
- [ ] 命令
- 十、判断
- 十一、循环
- 范围型遍历
- 数值型遍历
- 死循环处理
- 十二、函数
- 十三、exit
- 十四、文件重定向
- 十五、引入外部脚本
- shell 是我们通过命令行与操作系统沟通的语言
- 执行
- 可以在终端命令行中执行
- 将 shell 命令组成一个文件(脚本),方便复用
- 在终端执行 bash filename ,或者将 shell 命令写在一个文件夹中 ./filename 文件要具有可执行的权限,执行的时候路径可以绝对路径也可以是相对路径
shell 中的变量本质上都是字符串
name1='yjx' # 单引号定义字符串 name2="yjx" # 双引号定义字符串 name3=yjx # 也可以不加引号,同样表示字符串2. 注释
注释用 #
3. 取变量中的值需要加上$符号,或者${}符号。花括号是可选的,主要为了帮助解释器识别变量边界。
name="yjx"
echo $name
echo ${name}
4. 只读变量
readonly 或者 declare 修饰可以将变量变为只读。
5. 删除变量使用 unset 删除一个变量之后这个变量就不存在了,值为空字符串
name=yjx unset name6. 字符串
-
定义:字符串可以用单引号,也可以用双引号,也可以不用引号。单引号中的内容不好能转义( ),不能读取变量,不能执行;双引号中的内容可以转义( ),可以读取变量,可以执行。
-
获取字符串长度
name="yjx"
echo ${#name} # 输出3
- 提取子串
name="hello, yxc"
echo ${name:0:5} # 提取从0开始的5个字符
三、默认变量
设置好的特殊变量,可以拿来直接用
- $0:执行的文件名(包含路径),$1:命令行后的第一参数,$2:命令行后的第二参数
-
$#:取长度(参数),$*:以字符串的形式返回所有的参数(由所有参数构成的用空格隔开的字符串,如上例中值为 "$1 $2 $3 $4"),$@ 每个参数分别用双引号括起来的字符串,如上例中值为 "$1" "$2" "$3" "$4"
-
$?: 上一条命令的退出状态(exit code)。一个进程 return 0 表示正常退出,其他值表示错误,其中 0 和 其他值就是退出状态即 exit code
-
命令的标准输出 stdout
类似于 js 中数组的用法,数组中可以存放多个不同类型的值,只支持一维数组,初始化时不需要指明数组大小,数组下标从 0 开始,下标可跳。
1. 定义# 方式 1 array=(1 abc "def" yjx) # 每个数组元素用空格隔开:array[0]=1,array[1]=abc ...
# 方式 2:直接定义数组中某个元素的值 array[0]=1 array[1]=abc array[2]="def" array[3]=yjx2. 取数组中元素的值
注意:$():是获取 stdout 的值,${}:是获取变量的值
${array[index]}
array=(1 abc "def" yjx)
echo ${array[0]}
echo ${array[1]}
echo ${array[2]}
echo ${array[3]}
3. 读取整个数组
@ 和 *:取所有
${#array[@]} # 第一种写法
${#array[*]} # 第二种写法
4. 取数组长度
$# :取长度,长度不是按下标来算,而是按照实际用到的下标数量来算
array=(1 abc "def" yjx)
echo ${#array[@]} # 第一种写法
echo ${#array[*]} # 第二种写法
五、expr
-
作用:用于作运算,bash中不可直接作运算,作运算时需要借助 expr 命令。expr 将运算的结果返回到 stdout 中,取运算结果时需要用 $() 或者 ``
-
格式:expr 表达式,表达式的说明如下
-
表达式说明
- 用空格隔开每一项(一个命令后面的所有参数都需要用空格隔开)
- 对包含空格和其他特殊字符的变量要用引号括起来,避免报错
- expr会在stdout中输出结果。如果为逻辑关系表达式,则结果为真,stdout为1,否则为0。
- expr的exit code:如果为逻辑关系表达式,则结果为真,exit code为0,否则为1。
-
表达式为字符串表达式
-
表达式为整数表达式
- 支持 + - * / (),其中 * 和 () 需要用 进行转义
- 优先级:字符串表达式 > 这整数表达式 > 逻辑表达式
-
表达式为逻辑表达式
-
| 和 &,等价于 C++ 中的 || 和 &&,使用时需要转义
- a | b:
- 如果 a 是非空或非0时,返回 a 的值,b 不计算。
- 如果 a 是 0 或 空字符串,b 不为 0 或空则返回 b 的值,b 也同时为 0 或空则返回 0
- a & b:
- 如果 a 是 0 或者空时,返回 0 或 空,b 不计算
- 如果 a 不是 0 或非空时,b 为 0 或空时返回 0,b 不为 0 或空则返回 a 的值
- a | b:
-
< <= == != >= >
- 比较两端的参数,如果为true,则返回1,否则返回0
- 需要转义,可以用 和 ' '
-
() 可以该表优先级,但需要用反斜杠转义
-
-
读取单行数据到某个变量里
七、echo用于输出字符串,注意:“” 和 '', "" 可以读取字符串变量、进行转义,'' 不可以
八、printf用于格式化输出,用法类似于 C/C++
九、test 与 [ ] && 和 ||- && 和 || 是 bash 中自带的逻辑运算符,用法和 C++ 中的类似。 & 和 | 是 expr 命令中自己定义的
- 用短路原则实现 if-else 的作用
- 命令串联操作:a && b || c
- a && b:a 为假时,忽略 b;a 为真时,执行 b
- a || b:a 为真时,忽略 b;a 为假时,执行 b
- 作用:用于判断文件类型以及比较两个元素(整数和字符串)值
- test 命令用 exit code 返回结果,0 表示真,非0 表示假。获取 exit code 的值用 $?(查看上一条命令的退出状态)
- 用进程状态表示结果,0 表示真,1 为假;用输出表示结果,1 为真,0 为假
| 命令 | 表示 | 结果 |
|---|---|---|
| expr | stdout | 1表示真,0表示假 |
| test | exit code | 0表示真,1表示假 |
test 和 expr 的功能有重合:可以判断一个表达式是否为真,格式为 test 表达式,看结果用 $?,下面几个为具体类型的操作。
- 文件类型判断,文件权限判断
格式:test 参数 filename ,参数:-r -w -x -s
test -r filename # 判断文件是否可读
- 整数间的比较
格式:test $a 参数 $b ,参数:-eq -ne -gt -lt -ge -le
test $a -eq $b # a是否等于b [ $a -eq $b ]
- 字符串间的比较
- [ ] 命令可以替代 test 命令
- [ ] 是一个命令,所以括号中的每个参数都要用空格隔开,括号内取变量值的时候最好将 $ 和变量一同用 "" 括起来
- 单层 if
if 表达式 then 语句1 语句2 ... fi
- 单层 if - else
if condition
then
语句1
语句2
...
else
语句1
语句2
...
fi
- 多层 if-elif-elif-else
if condition
then
语句1
语句2
...
elif condition
then
语句1
语句2
...
elif condition
then
语句1
语句2
else #最后的 else 可省
语句1
语句2
...
fi
十一、循环 范围型遍历
for ... in ... do ... done ... (do 和 done 类似于 C++ 中的左括号和右括号)
- 形式 1
#var 为变量,val1 val2 val3 分别为值1 值2 和值3(属于一个范围),var 会枚举范围里的每一个值,对于每一个值都进行一个循环
for var in val1 val2 val3 #
do
语句1
语句2
...
done
- 形式 2
# seq a b 会返回一个从 a 到 b 的序列,每个用回车隔开
for i in $(seq 1 10)
do
echo $i
done
- 形式 3
bash 中自带的一个范围遍历 {1..20} {a..z}
for i in {1..20}
do
echo $i
done
数值型遍历
类似于 C++,格式如下
for ((expression; condition; expression))
do
语句1
语句2
done
for ((int i = 1; i <= 10; i ++ )) # 括号里面可以加空格 do echo $i done死循环处理
- 结束一个进程用 ctrl + q 或者 q
- ps aux:显示当前打开的所有进程,或者 top(shift + m 按内存排序显示)查看进程 PID,kill -9 PID即可杀掉此进程
- 定义
func_name() {
语句1
语句2
...
}
-
调用
直接写函数名即可,不用加 () -
函数参数
- 向函数传参数
- 函数中获取命令参数,$1 第一个参数,$2 第二个参数,依次类推,$0 表示文件名并不是函数名
-
return:返回的是退出状态(exit code),0 表示函数正常结束,非 0 表示不是正常退出,不写 return 默认返回 0
-
函数的输出内容或者返回内容通过在函数中使用 echo 将内容返回到 stdout 中,然后通过 $(函数名) 获取函数的输出内容或者返回值
- 用于退出当前进程
- 并返回一个退出状态,0 表示正常退出,1 表示失败,用 $? 来获取退出状态
- 重定向:从终端输入改为从文件输入,输出到终端里改为输出到文件里
- 进程:每一个程序在执行的过程中都是一个独立的进程
- 在 Linux 中每一个进程在执行时都会默认打开 stdin(标准输入,从终端读取数据,文件描述符为0)、stdout(标准输出,向终端输出数据,文件描述符为1)、stderr (准错误输出,向命令行输出数据,文件描述符为2)这三个文件,文件描述符即文件的一个 id
- >文件名:覆盖,>>文件名:向文件里追加内容
引入外部脚本类似于 C++ 中的 includ 头文件,关键字为 source 或者 .,引入的外部脚本无需有可执行权限具有可读权限即可
source filename .filename



