Shell 脚本
Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写的文本编辑器和一个能解释执行的脚本解释器就可以。
Bash 是大多数 Linux 系统默认的 Shell
一般情况下,不区分 Bourne Shell 和 Bourne Again Shell 所以,像 #! /bin/sh , 它同样可以改为 #! /bin/bash
#! 是告诉系统气候路径所指定的程序是解释此脚本呢的 Shell 程序
第一个 Shell 脚本
#! /bin/bash
echo "Hello Word!"
vim 创建 test.sh 文件中写入上述代码
分配可执行权限
chmod +x ./test.sh
或者 chmod 111 ./test.sh
执行脚本程序
./test.sh
获得输出 Hello Word!
Shell 变量
-
定义变量不需要加美元符号 $
-
命名只能字母,数字,下划线 且不能为数字开头
-
不能使用 bash 关键字
-
使用变量需要加美元符号 $
-
使用时花括号 {} 可选,加不加都行
使用:
#! /bin/bash
my_name="PupilXiao"
echo $my_name
echo ${my_name}
- 默认变量可以二次赋值,并且二次赋值的时候不需要使用 $
- 使用
readonly
可以将变量设置为只读变量,只读变量不允许二次赋值,否则报错变量名: This variable is read only.
- 使用
unset
命令可以删除变量,但是unset
不能删除只读变量,否则报错cannot unset: readonly variable
使用:
#! /bin/bash
my_name="PupilYE"
echo $my_name
my_name="PupilXiao"
echo ${my_name}
readonly my_name
my_name="Pupil" # 这里会报错 my_name: This variable is read only
host="localhost"
echo $host
unset host
echo $host # 这里不会有任何输出
unset my_name # 这里报错 cannot unset: readonly variable
字符串
字符串是最常用最有用的数据类型,可以使用单引号,也可以使用双引号,还可以不用引号,但是建议使用双引号:双引号里面可以有变量,可以有转义字符
str=abcde
str='abcde'
str="abcde" # 这三种定义方式都能通过
-
字符串拼接(使用双引号),可以使用如下两种拼接方式
my_name="PupilXiao" greeting="Hello! "$my_name"!" greeting="Hello! ${my_name}!"
-
获取字符串长度
str="abcd" echo ${#str} # #字符串 为字符串的长度,当 str 为数组时, #str <=> #str[0]
-
获取子字符串
str="Hello! PupilXiao!" echo ${str:1:4} # 从下标为 1 开始截取 4 个字符,这里输出 ello
-
查找子字符串
str="Hello! PupilXiao!" echo `expr index "$str" io` # 使用反引号 `,从 str 中查询 i 或者 o 从第几个单词开始,返回最先匹配到的序列,这里返回 5,对应第一个 o 位置
数组
shell 脚本中使用 () 来表示数组,元素之间使用 空格或者换行符 分割开
例: names=("PupilXiao" "YeZhiGang" "XiaoXiaoSheng")
或者:
names[0]="PupilXiao"
names[1]="YeZhiGang"
names[2]="XiaoXiaoSheng"
-
读取数组,使用 @ 可以获取数组所有元素
echo ${names[0]}
echo ${names[@]}
-
获取数组长度
echo ${#names[@]}
或者echo ${#names[*]}
-
关联数组(效果类似 Map )
declare -A name_age=(["PupilXiao"]="21" ["小玉"]="17" ["王亮"]="25") echo ${name_age["PupilXiao"]} # 获取到 21
注释
-
单行注释
# 单行注释直接使用 # 进行定义
-
多行注释
# 多行注释有两种 :<<EOF 这里可以编写注释 EOF # EOF 也可使用其他字符代替 :<<' 这里编写注释 ' # 或者 :<<! 这里编写注释 !
Shell 传参
在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n, n代表一个数字,指定第 n 个参数,从下标为 0 开始,其中第 0 个参数为文件名
#! /bin/bash
# 使用传参
# 假设调用 ./test.sh abc ab a
echo "Shell 脚本传递参数"
echo "第 0 个参数,文本名: $0" # 第0个参数值 ./test.sh
echo "第 1 个参数,执行传递: $1" # 第1个参数值 abc
echo "第 2 个参数,执行传递: $2" # 第2个参数值 ab
echo "第 3 个参数,执行传递: $3" # 第3个参数值 a
echo "获取传参个数:$#"
echo "所有的传入参数: $*"
echo "获取执行脚本的进程ID号:$$"
Shell 运算符
-
算数运算符
+ 加法 expr $a + $b
- 减法 * 乘法 / 除法 % 取余 = 赋值 == 相等 if [ $a == $b ] != 不等 if [ $a != $b ] -
关系运算符
-eq 等于 if [ $a -eq $b]
-ne 不等于 if [ $a -ne $b ]
-gt 大于 if [ $a -gt $b]
-lt 小于 if [ $a -lt $b]
-ge 大于等于 if [ $a -ge $b]
-le 小于等于 if [ $a -le $b]
-
布尔运算符
! 非运算 -o 或运算同逻辑运算 || -a 与运算同逻辑运算 && -
字符串运算符
= 检测两个字符串是否相等 if [ $a = $b]
!= 检测两个字符串是否不等 -z 检验字符串长度是否为0 if [ -z $a ]
-n 检验字符串长度是否不为0 if [ -n $a ]
$ 检测字符串是否不为空 if [ $a ]
-
文件测试运算符
-b file 检测是否块设备文件 -c file 检测是否字符设备文件 -d file 检测文件是否目录 -f file 检测文件是否普通文件 -g file 检测文件是否设置SGID位 -k file 检测文件是否设置了粘着位 -p file 检测文件是否有名管道 -u file 检测文件是否设置SUID位 -r file 检测文件是否可读 -w file 检测文件是否可写 -x file 检测文件是否可执行 -s file 检测文件是否为空 -e file 检测文件是否存在
echo 命令
-
显示普通字符串
echo "It is a test"
-
显示转义字符
echo "\"It is a test\""
-
显示变量
echo "$a Use variable"
-
显示换行
echo -e "ok! \n"
-e 开启转义 -
显示不换行
echo -e "ok! \c"
-
显示结果定向至文件
echo "It is a test" > myfile
-
原样输出字符串(不转义或取变量,使用单引号)
echo '$name\"'
-
显示命令执行结果,用反引号
echo `date`
printf 命令
test 命令
Shell 流程控制
同其他语言不一样,Shell 命令中的流程控制语句不能为空
Shell 的流程控制语句很多都是 用反写来表示结束
-
if 流程控制语句,需要使用 fi 结尾
-
if fi
if condition then command... # 注意不能有 else,应为 else 不能为空 fi
-
if else fi
if condition then command... else command... fi
-
if else-if else fi
if condition then command... elif condition2 then command... else commandN fi
-
-
for 循环
for name in PupilXiao YeZhiGang XiaoXiaoSheng do echo "current element is ${name}" done
-
while 循环
while condition do command... done
-
until 循环
until condition do command done
-
case ... esac => switch case
read num case $num in 1) echo '你输入了 1' ;; # 两个分号表示 break 2) echo '你输入了 2' ;; 3) echo '你输入了 3' ;; *) echo '你输入了其他的数组' ;; esac
-
跳出循环
- break
- continue
Shell 函数
[ function ] funname [()]
{
command...
[return int]
}
使用实例
demoFun(){ # 定义函数
echo "Test Function Of DemoFun!"
}
demoFun # 执行函数,不传入任何参数
:<<EOF
也可以使用 function 显示定义函数
function demoFun(){
echo "显示定义函数"
}
EOF
# 定义有返回值和参数的 函数
demoFun(){
echo "第一个参数 $1"
return "你好,我是返回值"
}
demoFun
echo "函数返回值 $? " # 函数返回值在调用函数后使用 $? 获得
Shell 输入输出重定向
command > file | 输出重定向到 file | |
---|---|---|
command < file | 输入重定向到 file | |
command >> file | 输出以追加的方式重定向到 file | |
n > file | 文件描述符为 n 的文件重定向到file | |
n >> file | 以追加的方式重定向 | |
n >& m | 输出文件 m 和 n 合并 | |
n <& m | 将输入文件 m 和 n 合并 | |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入 |