导图社区 Shell脚本基础学习笔记
主要梳理了Linux Bash Shell 脚本语言的基础知识,从变量到流程控制到函数,还包括了相关使用技巧。
编辑于2020-11-17 22:13:27Shell脚本基础学习笔记
执行方式
1、赋与可执行权限后 ./xxx.sh 或/bin/bash xxx.sh 结果是会新起一个进程来执行 2、source xxx.sh 或 . xxx.sh 结果是不会新起一个进程来执行,不需要可执行权限
使用命令的执行结果
` `
$( ) 如$(seq 2 2 100)
命令类型
内建命令:由 Bash 自身提供的命令
外部命令:文件系统中的某个可执行文件,通过$PATH变量定义路径
使用type 来确定一个命令是否是内建命令
区别:内建命令会比外部命令执行得更快,执行外部命令时不但会触发磁盘 I/O,还需要 fork 出一个单独的进程来执行,执行完成后再退出。而执行内建命令相当于调用当前 Shell 进程的一个函数
特殊变量
$0 当前脚本的文件名。 $n 传递给脚本或函数的参数。n是一个数字,表示第几个参数。 $# 传递给脚本或函数的参数个数 $* 传递给脚本或函数的所有参数 $@ 传递给脚本或函数的所有参数。当被双引号""包含时,$@与$*稍有不同。 $?上个命令的退出状态,或函数的返回值 $$ 当前 Shell进程ID。对于 Shell脚本,就是这些脚本所在的进程ID。
字符串定义与使用 (可以是数字或字符)
如果不加以说明, Shell 的值都是字符串
单引号
1、单引号里面是什么就输出什么,在其中使用变量是无效的 2、字符串中不能出现单引号,即使对单引号进行转义也不行
双引号
变量会被解析,字符串中可以出现双引号,只要它被转义了就行
没引号
变量会被解析,不能出现空格
使用${ } 这样可以与相连的字符做区分,推荐给所有变量加上花括号{ }
使用unset命令删除变量
获取字符串长度:${#string_name},如echo ${#str}
字符串截取
从字符串左边开始计数:${string: start :length},从 0 开 始计数,结果不包括start位置的字符,如url="www.shell.com" echo ${url: 2: 6} 结果为.shell,不指定:length则到末尾
从右边开始计数:${string: 0-start :length},0-,这是固定的写法,专门用来 表示从字符串右边开始计数,从 1 开始计数,结果包括start位置的字符(其实也可以理解为从 0 开始计数,结果不包括start位置的字符),如url="www.shell.com" echo ${url: 0-9: 5} 结果为shell,不指定:length则到末尾
使用 # 号截取右边字符:${string#*chars}遇到第一个cahrs就结束 ${string##*chars} ##遇到最后一个chars才结束,chars不会被截取,不写*就是严格匹配
使用 % 截取左边字符:${string%chars*},${string%%*chars}从 string 字符串最后一次出现 *chars 的位置开始,截取chars* 左边的所有字符。
数组
用括号( )来表示数组,数组元素之间用空格来分隔。弱类型,不要求所有数组元素的类型必须相同;数组的长度不是固定的。array_name=([0]=11 [3]="xxx") 使用数组元素:${array_name[index]}; 获取所有元素:${array_name[*]}或${array_name[@]} 获取数组长度:${#array_name[@]}或${#array_name[*]} 数组拼接:array_new=(${array1[@]} ${array2[@]})
条件判断
用 (( )) 来处理整型数字,用 [[ ]] 来处理字符串或者文件,类似与C语言
(( ))用于整数运算,效率很高, 推荐使用
[[ ]] 是 Shell 内置关键字,不是命令,是 test 的升级版
[[ ]] 支持逻辑运算符,[[ ]] 剔除了 test 命令的-o和-a选项, 你只能使用 || 和 &&
[[ ]] 支持正则表达式:[[ str =~ regex ]]
不建议使用test 或者 [ ],[[ ]] 完全可以替代之, 而且更加方便,更加强大
文件判断: -e filename 判断文件是否存在 -s filename 判断文件是否存在,并且是否为非空 -b 块、-c 字符、-d 目录、-f 普通文件、-L 符号链接、-p 管道、-S 套接字文件; -r 读、-w写、-x 执行、-u SUID、-g SGID、-k SBIT 权限; filename1 -nt filename2 判断 filename1 的修改时间是否比 filename2 的新。 filename -ot filename2 判断 filename1 的修改时间是否比 filename2 的旧。 filename1 -ef filename2 判断inode 号一致,即是否为同一个文件,用于判断硬链接
字符串判断: -z str 判断字符串 str 是否为空。 -n str 判断宇符串 str 是否为非空。
if语句
if condition1 then statement1 elif condition2 then statement2 else statementn fi
caase in
case expression in pattern) statement1 ;; …… *) statementn esac
expression 既可以是一个变量、一个数字、一个字符串,还可以是一个数学计算表达式,或者是命令的执行结果,只要能够得到 expression的值就可以
pattern 可以是一个数字、一个字符串,甚至是一个简单的正则表达式
正则表达式
* 表示任意字符串。 [abc] 表示 a、 b、 c 三个字符中的任意一个。比如, [15ZH] 表示 1、 5、Z、 H 四个字符中的任意一个。 [m-n] 表示从 m 到 n 的任意一个字符。比如, [0-9] 表示任意一个数字,[0-9a-zA-Z] 表示字母或数字。 | 表示多重选择,类似逻辑运算中的或运算。比如, abc | xyz 表示匹配字符串 "abc" 或者 "xyz"。
;;和*)就相当于C语言中的 break 和 default,中间分支都必须以;;结尾
while循环
while condition do statements done
until循环
until condition do statements done
for循环
C语言风格
for((exp1; exp2; exp3)) do statements done
Python风格
for variable in value_list do statements done
Value_list
直接给出具体的值:for n in 1 2 3 4 5 6
给出一个取值范围:for n in {1..100}
使用命令的执行结果:for n in $(seq 2 2 100)
使用 Shell 通配符:for filename in *.sh
使用特殊变量:$#、 $*、 $@、 $?、 $$ 等
select in 循环
用来增强交互性,它可以显示出带编号的菜单,用户输入不同的编号就可以选择不同的菜单,并执行不同的功能。 select in 是 Shell 独有的一种循环,非常适合终端(Terminal)这样交互场景, C语言、 C++、 Java、Python、 C# 等其它编程语言中是没有的。
函数
function name() { statements [return value] }
Shell 中的函数在定义时不能指明参数,但是在调用时却可以传递参数。并且给它传递什么参数它就接收什么参数。函数参数是Shell位置参数的一种,在函数内部可以使用$n等位置参数来接收
Shell 也不限制定义和调用的顺序,你可以将定义放在调用的前面,也可以反过来,将定义放在调用的后面。
调用函数名字后面不管带不带参数都不需要带括号
getsum 10 20 55 15 #调用函数并传递参数 echo $?
total=$(getsum 10 20 55 15) echo $total
也可以将变量省略 echo $(getsum 10 20 55 15)