Shell概述
Shell是一个命令解释器,它给用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序。
脚本格式
#!/bin/bash
#!是说明这个文件的类型,有点类似于Windows系统下用不同文件后缀来表示不同文件类型的意思(但不相同)
使用分号;可以在同一行上写两个或两个以上的命令
#需要可执行文件的权限
#!/bin/bash
echo hello; echo there
filename=ttt.sh
if [ -e "$filename" ]; then
echo "File $filename exists."; cp $filename $filename.bak
else
echo "File $filename not found."; touch $filename
fi; echo "File test complete."
使用双引号;;终止case选项
执行脚本方式
chmod u+x filename
./ filename
等价于 bash filename
等价于 source filename
等价于 . filename
bash 中的 source 命令用于在当前 bash 环境下读取并执行 FileName.sh 中的命令。
Shell符号规则
引号
双引号(")
“STRING” 将会阻止(解释)STRING 中大部分特殊的字符。后面的实验会详细说明。
单引号(’)
‘STRING’ 将会阻止 STRING 中所有特殊字符的解释,这是一种比使用"更强烈的形式。后面的实验会详细说明。
斜线(/ )
文件名路径分隔符。多个/根一个效果相同
反斜线(\ )
一种对单字符的引用机制。\X 将会“转义”字符 X。这等价于"X",也等价于’X’。\ 通常用来转义双引号(" )和单引号(' ),这样双引号和单引号就不会被解释成特殊含义了。
反引号
表示执行引号内的语句
冒号
空命令
等价于“NOP”(no op,一个什么也不干的命令)。也可以被认为与 shell 的内建命令 true 作用相同。“:”命令是一个 bash 的内建命令,它的退出码(exit status)是(0)。
如:
#!/bin/bash
while :
do
echo "endless loop"
done
等价于
#!/bin/bash
while true
do
echo "endless loop"
done
变量扩展/子串替换
在与 > 重定向操作符结合使用时,将会把一个文件清空,但是并不会修改这个文件的权限。如果之前这个文件并不存在,那么就创建这个文件。
: > test.sh
: 还用来在 /etc/passwd 和 $PATH 变量中做分隔符,如:
echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games
cop
问号
测试操作符
在一个双括号结构中,? 就是 C 语言的三元操作符
美元符号
变量替换
小括号()
1.命令组
在括号中的命令列表,将会作为一个子 shell 来运行。
在括号中的变量,由于是在子 shell 中,所以对于脚本剩下的部分是不可用的。父进程,也就是脚本本身,将不能够读取在子进程中创建的变量,也就是在子 shell 中创建的变量。
2.初始化数组
#!/bin/bash
arr=(1 4 5 7 9 21)
echo ${arr[3]}
bash test
大括号{}
1、文件名扩展
注意: 在大括号中,不允许有空白,除非这个空白被引用或转义。
2、代码块
代码块,又被称为内部组,这个结构事实上创建了一个匿名函数(一个没有名字的函数)。然而,与“标准”函数不同的是,在其中声明的变量,对于脚本其他部分的代码来说还是可见的。
#!/bin/bash
a=123
{ a=321; }
echo "a = $a"
运行结果:a=321
中括号
1、条件测试
条件测试表达式放在 [ ] 中。下列练习中的 -lt (less than)表示小于号。
2、数组元素
在一个 array 结构的上下文中,中括号用来引用数组中每个元素的编号。
尖括号
重定向
test.sh > filename :重定向 test.sh 的输出到文件 filename 中。如果 filename 存在的话,那么将会被覆盖。
test.sh &> filename :重定向 test.sh 的 stdout(标准输出)和 stderr(标准错误)到 filename 中。
test.sh >&2 :重定向 test.sh 的 stdout 到 stderr 中。
test.sh >> filename :把 test.sh 的输出追加到文件 filename 中。如果 filename 不存在的话,将会被创建。
竖线
管道
分析前边命令的输出,并将输出作为后边命令的输入。这是一种产生命令链的好方法。
tr :表示替换
#!/bin/bashtr 'a-z' 'A-Z'exit 0
chmod 755 test26.shls -l | ./test26.sh
输出的内容均变为了大写字母。
破折号
选项、前缀
在所有的命令内如果想使用选项参数的话,前边都要加上“-”。
用于重定向stdin或stdout
波浪号
目录 ~表示home目录
Shell运算规则
变量定义
变量的名字就是变量保存值的地方。引用变量的值就叫做变量替换。
如果 variable 是一个变量的名字,那么 $variable 就是引用这个变量的值,即这变量所包含的数据。
$variable 是
v
a
r
i
a
b
l
e
的
简
写
形
式
,
如
果
遇
到
有
时
候
{variable}的简写形式,如果遇到有时候
variable的简写形式,如果遇到有时候variable引起错误,改为${variable}
注意:变量名和等号之间不能有空格
变量名命名规则:
- 首个字符必须为字母(a-z,A-Z)。
- 中间不能有空格,可以使用下划线(
_ )。 - 不能使用标点符号。
- 不能使用 bash 里的关键字(可用 help 命令查看保留关键字)。
也可以进行语句给变量赋值
for file in `ls /etc`
只读变量
使用readonly命令可以将变量定义为只读变量,只读变量的值不能改变
#!/bin/bashmyUrl="http://www.shiyanlou.com"readonly myUrl
特殊变量
局部变量
这种变量只有在代码块或者函数中才可见
环境变量
这种变量将影响用户接口和shell的行为。在通常情况下,每个进程都有自己的“环境”,这个环境是由一组变量组成的,这些变量中存有进程可能需要引用的信息。在这种情况下,shell 与一个一般的进程没什么区别。
位置参数
从命令行传递到脚本的参数:$0 ,$1 ,$2 ,$3 …$0 就是脚本文件自身的名字,$1 是第一个参数,$2 是第二个参数,$3 是第三个参数,然后是第四个。$9 之后的位置参数就必须用大括号括起来了,比如,${10} ,${11} ,${12} 。
$# : 传递到脚本的参数个数$* : 以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过 9 个$$ : 脚本运行的当前进程 ID 号$! : 后台运行的最后一个进程的进程 ID 号$@ : 与 $* 相同,但是使用时加引号,并在引号中返回每个参数$ : 显示 shell 使用的当前选项,与 set 命令功能相同(注意:显示当前shell中所有变量:set)$? : 显示最后命令的退出状态。 0 表示没有错误,其他任何值表明有错误。
#!/bin/bash
# 作为用例, 调用这个脚本至少需要10个参数, 比如:
# bash test.sh 1 2 3 4 5 6 7 8 9 10
MINPARAMS=10
echo
echo "The name of this script is \"$0\"."
echo "The name of this script is \"`basename $0`\"."
echo
if [ -n "$1" ] # 测试变量被引用.
then
echo "Parameter #1 is $1" # 需要引用才能够转义"#"
fi
if [ -n "$2" ]
then
echo "Parameter #2 is $2"
fi
if [ -n "${10}" ] # 大于$9的参数必须用{}括起来.
then
echo "Parameter #10 is ${10}"
fi
echo "-----------------------------------"
echo "All the command-line parameters are: "$*""
if [ $# -lt "$MINPARAMS" ]
then
echo
echo "This script needs at least $MINPARAMS command-line arguments!"
fi
echo
exit 0
撤销变量
unset 变量
算数运算符
注意:表达式和运算符之间要有空格 $a + $b 写成 $a+$b 不行
**注意:**条件表达式要放在方括号之间,并且要有空格 [ $a == $b ] 写成 [$a==$b] 不行
**注意:**乘号(* )前边必须加反斜杠(\ )才能实现乘法运算
关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
0为真,1为假
逻辑运算符
注意:
字符串运算符
注意:-z 和 -n 两个是反的,建议还是 -z较好
? str指的是字符串本身
文件测试运算符
注意:-e 判断文件是否存在 -f 表示文件为一般类型
? expr 只能用于整数计算,可以使用 bc 或者 awk 进行浮点数运算。
? expr 用法: echo ``expr 1+2 输出为3
浮点数运算实验
#!/bin/bashradius=2.4pi=3.14159girth=$(echo "scale=4; 3.14 * 2 * $radius" | bc)area=$(echo "scale=4; 3.14 * $radius * $radius" | bc)echo "girth=$girth"echo "area=$area"
scale表示指定保留小数点后的位数,不设定就默认为0
Shell语句
if else语句
if语句
if conditionthen
command1
command2 ...
commandN
fi
if else语句
if conditionthen
command1
command2 ...
commandN
else
commandfi
if-elif-else 语法格式
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
实验一、if else使用判断两个变量
#!/bin/bash
a=10
b=20
if [ $a -eq $b ]
then
echo "a=b"
elif [ $a -gt $b ]
then
echo "a>b"
elif [ $a -lt $b ]
then
echo "a<b"
else
echo "Ineligible"
fi
输出结果: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nngXgslS-1630919748580)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905161407342.png)]
if else 语句经常与test命令结合使用
num1=$[2*3]
num2=$[1+5]
if test $[num1] -eq $[num2]
then
echo 'Two numbers are equal!'
else
echo 'The two numbers are not equal!'
fi
输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y1e8pjzi-1630919010305)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905161912580.png)]
for循环
for循环的一般格式为:
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
实验二 顺序输出fujingwen
2
3 for str in Hello fu jing zhu
4 do
5 echo $str
6 done
输出结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3r5R94VQ-1630919010306)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905162341346.png)]
while循环
while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件 格式为:
while condition
do
command
done
实验三、计算1到100之和
1
2
3 i=1
4 while (( $i<=100 ))
5 do
6 s=$[ $s + $i ]
7 let "i++"
8 done
9 echo $s
输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3iibz2eH-1630919010307)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905163152722.png)]
这里使用了Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上$来表示变量
注意:
while循环可用于读取键盘信息。下面的例子中,输入信息被设置为变量MAN,按<Ctral + D>结束循环
echo "press <CTRL-D> exit"
echo -e "who do you think is the most handsome\n"
while read MAN
do
if [ $MAN -eq 201931773444 ]
then
echo "Yes! hujie is really handsome"
else
echo "SB"
fi
done
无限循环
格式
while :
do command
done
或者
while true
do
command
done
或者
for (( ; ; ))
until循环
until循环执行一系列命令直至条件为真时停止。until循环与while循环在处理方式上刚好相反。一般情况while优先于until循环,但在极少数的时候,until循环更加有用。until的格式如下
until condition
do
command
done
条件可为任意测试条件,测试发生在循环末尾,因此循环至少执行一次—请注意这一点。
case
Shell case语句为多选择语句。可以用case语句匹配一个值与一个模式,入如果匹配成功,执行相匹配的命令。case语句格式如下
case 值 in
模式1)
command1
command2
...
commandN ;;
模式2)
command1
command2
... c
ommandN
;;
esac
取值后面必须为单词 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;; 。
取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。
实验四 case的使用
下面脚本提示输入1到4,与每一种模式匹配
echo "Enter a number between 1 to 4:"
echo "The number you entered is:"
read num
case $num in
1)
echo 'You have chosen 1'
;;
2)
echo 'You have chose 2'
;;
3)
echo 'You have chose 3'
;;
4)
echo 'You have chosen 4'
;;
*)
echo 'You did not enter a number between 1 to 4'
;;
e
输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fwdPasn8-1630919010308)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905165618616.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aXcxndmM-1630919010310)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905165648304.png)]
跳出循环
在循环过程中,有时候需要在为达到循环结束条件的时候强制跳出循环,Shell使用两个命令来实现该功能:break和continue
break命令
break命令允许跳出所有循环(终止执行后面的所有循环)
**注意:**每个case分支用右圆括号,用两个分号表示break
continue命令
continue命令与break命令相似,只有一点差别,它不会跳出所有的循环,仅仅跳出当前循环。
实验五 break的使用
脚本进入死循环直至用户输入数字大于5.要跳出这个循环,返回shell提示符下。需要使用break命令
while :
do
echo -n "Enter a number between 1 and 5:"
read num
case $num in
1|2|3|4|5) echo "The number you entered is $num!"
;;
*)echo "The number you entered is not between i and 5! game over!"
break
;;
esac
done
输出结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MYuYSQMz-1630919010310)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905192129865.png)]
实验六、continue的使用
while :
do
echo -n "Enter a number between 1 and 5:"
read num
case $num in
1 |2|3|4|5)echo "The number you entered is $num!"
;;
*)echo "The number you entered is not between 1 and 5!"
continue
echo "game over"
;;
esac
done
输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VzIGfrYo-1630919010311)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905192916861.png)]
实验七
写一个脚本实现以下功能
1)提示用户输入一个字符串
2)判断:如果输入的是quit,则退出脚本; 否则,则显示输出的内容
#!/bin/bash
echo -n "Please enter a string:"
read str
case $str in
quit) exit 1
;;
*) echo "You have entered is $str!"
;;
es
输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FTOPgqMx-1630919010312)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905193954703.png)]
实验八、找最值
判断8 、4 、5三个数的最大值
#!/bin/bash
echo "Please enter three numbers: "
read a b c
if [ $a -gt $b ]
then
d=$a
else
d=$b
fi
if [ $c -gt $d ]
then
echo "The largist number is $c"
else
echo "The largist number is $d"
fi
输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2f2tSRRy-1630919010314)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905195325914.png)]
实验九、求100以内所有偶数之和
#!/bin/bash
s=0
i=2
until [ $i -gt 100 ]
do
s=$[ $s + $i ]
i=$[ $i + 2 ]
done
echo $s
#!/bin/bash
cnt=0
sum=0
for cnt in `seq 2 2 100`
do
sum=$((cnt+sum))
done
echo $sum
seq 2 2 100 表示列出 1 到 100 的所有偶数
输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VZVsXQHb-1630919010315)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905200916087.png)]
函数
函数的定义
shell中函数的定义格式如下:
[ function ] funname [()]{
action;
[return int;]
}
说明:
? 1.可以带function fun()定义,也可以直接fun()定义,不带任何参数
? 2.参数返回,可以显示加:return返回,如果不加,将以最后一条指令运行结果,作为返回值。return后跟数值(0-255)
实验一、函数的定义被调用
#!/bin/bash
demoFun(){
echo "Hello world"
}
echo "----------"
demoFun
echo "----------"
? 输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZS24nj0r-1630919010316)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905203644029.png)]
下面定义一个带return语句的函数:
#!/bin/bash
funwithreturn(){
echo "Enter first number:"
read num1
echo "Enter seconded number:"
read num2
echo "The result of two number is : $[ $num1 + $num2 ]"
return $(($num1+$num2))
}
funwithreturn
echo $?
输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7rjapMGS-1630919010317)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905204401250.png)]
函数参数
在shell中,调用函数时可以向其传递参数。在函数体内部,通过$n的形式来获取参数的值,例如$1表示第一个参数,$2表示第二个参数
实验二、函数参数的获取
funwithreturn(){
echo "the fist parameter is $1"
echo "the second parameter is $2"
echo "the tenth parameter is $10"
echo "the tenth parameter is ${10}"
echo "the total number of parameter is $#"
echo "Outputs all parameter as a string $*"
}
funwithreturn 1 2 3 4 5 6 7 8 9 34 73
输出结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ei7u169n-1630919010318)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905205138814.png)]
注意:
$10 不能获取第十个参数,获取第十个参数需要 ${10} 。当 n>=10 时,需要使用 ${n} 来获取参数。
$#:表示输出元素总的个数
$*:表示输出所有的元素
实验三、猜数字游戏
首先让系统随机生成一个数字,给这个数字一个范围,让用户猜这个数字,对输出做出判断,并给出提示。
用while实现
#!/bin/bash
function randNum(){
echo "Please enter a number:"
while :
do
read num
if test $num -eq $1
then
echo "right"
exit 1
else
if [ $num -lt $1 ]
then
echo "Your number is smaller"
else
echo "Your number is largger"
fi
fi
done
}
randNum $[ $RANDOM%100+1 ]
输出结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YrEbR01F-1630919010319)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210905210230652.png)]
**注意:**随机数的表示方法 $RANDOM%100+1
输出结果因为我是直接笔记上传的,所以就没有弄好,大家见谅,但是都是没有问题的。而且Shell基础部分挺简单的,大家子集也会检验!
如果大家需要文档可以直接下载:https://download.csdn.net/download/m0_56145255/21964539
|