一、简介
使用C语言编写的
是一种应用程序,用于解释用户输入的命令,将命令传递给内核,也可以在其中进行编程。
shell之所以被称作shell是因为它隐藏了操作系统低层的细节,就像是给操作系统套上了一个壳。
常见的Shell:
- sh(Bourne shell是个人名,第一个流行的shell。UNIX版本都配有)
- csh(第二个流行起来的shell,类似于C,得名C shell)
- tcsh(csh的增强版,加入了命令补全功能)
- ash(轻量级的Shell)
- bash(Bourne Again Shell。Linux默认的shell,兼容sh「即sh编写的代码可以不加修改的在bash中运行」也有些区别,不影响使用)等。
Wikipedia中对于shell的描述:
A Unix shell is a command-line interpreter or shell that provides a command line user interface for Unix-like operating systems. The shell is both an interactive command language and a scripting language, and is used by the operating system to control the execution of the system using shell scripts.
二、实例
2.1 在子Shell(child shell)中运行Shell脚本
子Shell:当执行脚本时,系统创建一个父Shell的副本,子Shell继承父Shell的环境变量,但是不会修改父Shell的环境变量。
用途:bashsh用于独立运行脚本,变量不污染当前Shell
2.1.1 作为可执行程序
Shell脚本第一行告诉系统使用哪种Shell(解释器)执行该文件
实例说明:执行当前(./)目录中的test.sh脚本
作为可执行程序时,需要指定解释器
当指定是哪种解释器执行时,无论使用命令bash test.sh
sh test.sh
./test.sh
均使用的是Shell脚本首行指定的解释器(#!/bin/bash
)。./test.sh
依赖脚本首行的shebang
(#!/bin/bash
),如果首行没有shebang
,则使用当前Shell执行。
扩展:
#!
说明其中#
叫sharp
或者hash
;!
叫做感叹号或者bang
。合起来叫做shebang
2.1.2 作为解释器参数
作为解释器参数执行时,不需要在脚本的第一行(#!/bin/bash)指定解释器
在当前Shell中运行Shell脚本
source
.
运行时,在当前Shell中运行脚本。
用途:source
.
用于加载配置,变量对当前Shell生效。
# 方式一:
source env.sh
# 方式二:
. env.sh # . 是source的缩写形式
三、基础语法
1、Shell变量
1.1 HINT
Shell变量定义时不加“$”(美元符号),使用定义好的变量时加“$”符号
1.2 变量命名规则
可使用字母,数字,下划线,首字符不能是数字。
不能使用标点符号
变量名和符号之间不能有空格
1.3 Shell字符串
双引号里可以有变量、转义字符。
单引号中的变量是无效的
#!/bin/bash
echo "Hello World!"
your_name="jiaohl1" # 显式的直接赋值
# 使用变量
echo $your_name
echo ${your_name} # {}可加可不加
for skill in Java Redis C++ C Python;
do
echo "I am good at ${skill}Script"
done
# 已定义变量重新定义
your_name="xixihaha"
echo ${your_name}
myEmail="jiaohl1@163.com"
readonly myEmail # 只读变量 不能修改
myEmail="xixihaha@163.com"
unset myEmail # 删除变量
echo $myEmail
# 拼接字符串
String01="01"
String02="02,${String01}"
String03="abcd"
echo "${#String03}"
# 提取字符
String04="nishige haoren"
echo ${String04:1:4} # 输出 ishi
# 查找子字符
String05="runnoob is a great site"
echo `expr index "$String05" io` # 这里使用的是反引号` 输出第一次出现的字符的索引 o的索引5 从1开始
# 数组
array_01=(value01 value02 value03) # 数组使用()括号 数组的索引从0开始。
echo ${array_01[0]} # value01
array_02=(val01 val02 val03)
echo ${array_02[@]} # 输出数组的所有值。
array_03[0]=v01
array_03[1]=v02
array_03[2]=v03
echo ${array_03[@]}
# 多行注释方式一
:<<EOF
注释内容...
EOF
# 多行注释方式二:
:<<'
注释内容...
'
# 多行注释方式三:
:<<!
注释内容...
!
2、Shell传递参数
符号 | 含义 |
---|---|
$0 | 执行的文件名,包含文件路径。 |
$# | 参数个数 |
$$ | 脚本运行的当前进程ID号 |
$* | 单字符显示向脚本输入的参数 |
$@ | |
$! | 最后一个在后台启动的进行PID |
$- | |
$? | 最后命令退出的状态,0没有错误 |
#!/bin/bash
echo "Shell脚本传递参数实例!"
echo "Shell脚本文件的名称:$0"
echo "传递的第1个参数:$1"
echo "传递的第2个参数:$2"
echo "传递的第3个参数:$3"
echo "传递的第4个参数:$4"
echo "传递到脚本的参数个数:$#"
echo "脚本运行的当前进程ID号:$$"
echo "以单字符显示向脚本输入的参数:$*"
echo "后台运行的最后一个进程ID号:$!"
echo "类似 "$*",使用时加双引号"$@""
echo "显示 Shell使用的当前选项:$-"
echo "显示最后命令的退出状态,0表示没有错误:$?"
3、Shell数组
3.1 读取数组
#!/bin/bash
# 数组,可以存放多个值,但是不支持多维数组,支持一维
array01=(val1 val2 val3)
array02=(a b "A" d)
array03[0]=v0
array03[1]=v1
array03[2]=v2
# 读取数组元素值
echo "${array01[0]}"
echo "${array02[2]}"
echo "${array03[1]}"
3.2 关联数组(键值对形式的数组)
declare -A site=(["k1"]="v1" ["k2"]="v2" ["k3"]="v3")
echo "${site["k2"]}"
# 获取数组中的所有值
echo "*输出:${site[*]}"
echo "@输出:${site[@]}"
# 获取数组的所有键
echo "数组前加!:${!site[*]}"
echo "数组前加!:${!site[@]}"
# 获取数组的长度
echo "数组前加#:${#site[*]}"
echo "数组前加#:${#site[@]}"
4、Shell运算符
4.1 算数
HINT!“*”之前必须加反斜杠“\”,if [ $a == $b ] 必须有空格。
#!/bin/bash
a=21
b=5
val_01=`expr $a + $b`
echo "a + b=${val_01}"
val_02=`expr $a - $b`
echo "a - b=${val_02}"
val_03=`expr $a \* $b`
echo "a * b=${val_03}"
val_04=`expr $a / $b`
echo "a / b=${val_04}"
val_05=`expr $a % $b`
echo "a % b=${val_05}"
if [ $a == $b ]
then
echo "a等于b"
fi
if [ $a != $b ]
then
echo "a不等于b"
fi
4.2 关系
关系运算符支持数字不支持字符串
符号 | 含义 |
---|---|
-eq | 是否相等(equal) |
-ne | 不相等(Unequal) |
-gt | 大于(greater than) |
-lt | 小于(less than) |
-ge | 大于等于(greater equal) |
-le | 小于等于(less equal) |
4.3 布尔
符号 | 含义 |
---|---|
! | 非 |
-o | 或 |
-a | 与 |
4.4 逻辑运算符
符号 | 含义 |
---|---|
&& | 逻辑与 |
|| | 逻辑或 |
#!/bin/bash
a=100
b=200
if [[ $a -lt 250 && $b -gt 100]]
then
echo "返回true"
else
echo "返回false"
fi
4.5 字符串(返回值为True 或者 False)
符号 | 含义 |
---|---|
= | 是否相等 |
!= | 是否不相等 |
-z | 长度是否为0 为0则为真 |
-n | 长度是否不为0 不为0则为真 |
$ | 是否为不为空 |
4.6 文件测试(返回值为true false)
符号 | 含义 |
---|---|
-b | 文件是否是块设备文件(block) |
-c | 文件是否是字符设备文件(character) |
-d | 文件是否是目录(directory) |
-f | 文件是否为普通文件(file) |
-g | 文件是否设置了SGID位 |
-k | 文件是否设置了粘着位(Sticky Bit) |
-p | 文件是否是有名管道(pipeline) |
-u | 文件是否设置了SUID位 |
-r | 检测文件是否可读(read) |
-w | 检测文件是否可写(write) |
-x | 检测文件是否可执行(eXe) |
-s | 检测文件是否为空(文件大小是否大于0) |
-e | 检测文件(包括目录)是否存在(exist),如果是,返回true。 |
5、Shell echo命令
5.1 显示普通字符(双引号可以省略)
以上两句,效果完全相同
echo "It is a test"
echo It is a test
5.2 显示转义字符
echo "\"It is a test\""
输出结果:“It is a test”
5.3 显示变量
read name # 从标准输入中读取一行,并将输入的每个字段值指定给shell变量。
echo "${name} It is a test"
5.4 显示换行
echo -e "It is a test \n" # -e开启转义 \n 换行
echo "It is second line"
5.5 显示不换行
echo -e " It is a test \c" # \c 不换行
echo "It is second line"
5.6 显示结果定向至文件
5.7 原样输出字符串,不进行转义或取变量(使用单引号)
echo '${name}' # 使用单引号引用即可
5.8 显示命令执行结果
echo `date` # 使用反引号 `,不是单引号'
6、Shell printf命令
printf format-string [argments...] # format-string:格式控制字符串, [argments ]:参数列表
%s(字符串) %c(字符) %d(整型输出) %f(输出实数) 都是格式替代符。
%-10s表示一个宽度为10个字符(-表示左对齐,没有表示右对齐),包含任何字符的10个字符。
%-4.2f表示格式化为小数。一个宽度为4个字符,".2"表示两位小数
printf的转义序列
\c
\n
\v 垂直制表
\t 水平制表
\\
\r 回车
7、Shell test命令
检查某个条件是否成立。可以进行数值、字符和文件三个方面的测试
7.1 数值测试
-eq
-ne
-gt
-ge
-lt
-le
7.2 字符串测试
=
!=
-z
-n
7.3 文件测试
-e
-r
-w
-x
-s
-d
-f
-c
-b
8、Shell 流程控制
8.1 if else
if
then
语句
else
语句
fi
if condition1
then
语句
elif condition2
then
语句
else
语句
fi
condition中
[ ] 对应 -gt / -lt等
(( )) 对应> / <
8.2 for/whlie/until循环
# 无限循环
while true
do
command
done
# 或者
for (( ; ; ))
until condition
do
command
done
8.3 case … esac多选择语句
8.4 跳出循环
break命令
跳出所有循环
continue命令
跳出本次循环
9、Shell函数
#!/bin/bash
funWithReturn(){
echo "两数相加"
echo "输入第一个数字:"
read aNum
echo "输入第二个数字:"
read anotherNum
echo "两个数字分别是 $aNum 和 $anotherNum"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "函数返回值 $? !"
[jiaohl1@login04 Shell_study]$ ./test11.sh
两数相加
输入第一个数字:
12
输入第二个数字:
5
两个数字分别是 12 和 5
函数返回值 17 !
#!/bin/bash
funWithParam(){
echo "第1个参数:$1 !"
echo "第2个参数:$2 !"
echo "第10个参数:$10 !"
echo "第10个参数:${10} !"
echo "第11个参数:${11} !"
echo "参数总数:$# !"
echo "使用一个字符串将所有参数输出:$* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 17 81
[jiaohl1@login04 Shell_study]$ ./test12.sh
第1个参数:1 !
第2个参数:2 !
第10个参数:10 !
第10个参数:34 !
第11个参数:17 !
参数总数:12 !
使用一个字符串将所有参数输出:1 2 3 4 5 6 7 8 9 34 17 81 !
⚠️HINT:$10不能获取第10个参数,获取第10个参数需要使用${10}。当n>=10时,需要使用${n}来获取参数。
10、Shell输入/输出重定向
command > file 将输出重定向到file文件中。
command < file 将输入重定向到file文件中。
11、文件包含
被包含的文件不需要可执行权限
使用.号进行引用其他文件。注意 . ./test001.sh 中间有空格。