Shell基础
一、关于shell
什么是shell?
shell(外壳)是一个用C语言编写的程序,它是用户使用Linux的桥梁。shell既是一种命令语言,也是一种程序设计语言。
shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
什么是脚本?
脚本简单地说就是一段程序,这些文字命令是可以看到的(如可以通过记事本打开、查看、编辑)。
常见的脚本语言:JavaScript(JS,前端)、VBScript、ASP、JSP、PHP(后端)、SQL(数据库操作语言)、Perl、shell、python、JavaFX、Lua等。
为什么要学习shell?
shell属于内置的脚本
程序开发的效率非常高,依赖于功能强大的命令可以迅速的完成开发任务(批处理),语法简单,代码写起来比较轻松,简单易学。
常见的shell种类
在Linux中有很多类型的shell,不同的shell具备不同的功能,shell还决定了脚本的语法,Linux中默认的shell是/bin/bash,流行的shell有ash、bash、ksh、csh、zsh等,不同的shell都有自己的特点和用途。
csh : C shell 使用的是“类C”语法,csh是具有C语言风格的一种shell,其内部命令有52个,较为庞大,目前使用的并不多,已经被取代。
ksh : Korn shell的语法与Bourne shell相同,同时具备了C shell的易用特点,许多安装脚本都使用ksh,ksh有42条内部命令,与bash相比有一定的限制性。
tcsh : tcsh是csh的增强版,与C shell完全兼容。
sh : 是一种快捷方式,已经被/bin/bash取代。
zsh : 目前Linux里最庞大的一种shell,有84条命令,使用起来比较负责,一般情况下不会使用该shell。
bash : 大多数Linux默认使用的shell,它是最早的Unix shell,bash还有一个特点,可以通过help命令来查看帮助,包含的功能几乎可以涵盖shell所具有的功能,所以一般的shell脚本都会指定它为执行路径。
2、shell入门
编写规范:
①代码规范:
&emap; #!/bin/bash //指定告知系统当前这个脚本要使用的shell解释器
&emap; Shell相关命令
②文件命名规范:
&emap; 文件名.sh &emap; //.sh是Linux下bash shell的默认后缀
使用流程:
①创建.sh文件 &emap; //使用命令touch或vim
②编写shell代码
③执行shell脚本 &emap; //脚本必须得有执行权限
案例1:创建test.sh,实现第一个shell脚本陈程序,输出hello world。
输出命令:#echo 123
注意输出的内容如果包含字母和符号(不包含变量),则需要用引号包起来。如果是纯数字可以包也可以不包。
1 #!/bin/bash
2 echo 'hello world!'
注意:这里在运行时一定要写成./test.sh,而不是test.sh,运行其他二进制的程序也一样。直接写test.sh,linux系统会去PATH(环境变量)里寻找有没有叫test.sh的,而只有/bin,/sbin,/usr/bin,/usr/sbin等在PATH里,你的当前目录不在PATH里,所以写成test.sh是会找不到命令的,要用./test.sh告诉系统说,就在当前目录找。
案例2:使用root用户账号创建并执行test2.sh,实现创建一个shelltest用户,并在其家目录中新建文件try.html。
test2内容
#!/bin/bash
useradd shelltest
touch /home/shelltest/try.html
调试过程
[root@xia /]# ll test2.sh
-rw-r--r-- 1 root root 87 Aug 11 21:35 test2.sh
[root@xia /]# chmod +x test2.sh
[root@xia /]# ./test2.sh
Changing password for user shelltest.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.
[root@xia /]# ls /home/shelltest/
try.html
脚本运行的另一种方式:/bin/bash 脚本的路径(了解)
例如上面脚本#/bin/bash test2.sh
Shell脚本分为简单的写法(简单命令的堆积)和复杂写法(程序的设计)
二、shell进阶
1、变量(重点)
1.1、变量的含义
a.什么是量:量就是数据
b.什么是变量:数据可以发生改变的变量,在一个脚本周期内,其值可以发生改变的量就是变量。
c.什么叫做脚本周期
一个脚本周期可以简单的理解为当前的shell文件
变量是shell中不可或缺的部分,也是最基础最重要的组成部分。
1.2、变量的定义和使用
定义形如:class_name="yunwei"
使用形如:echo $class name //在使用变量名的时在前面添加$
变量就是由2部分组成,一个是变量名,另一个是变量的值
变量名和变量值是什么关系?
变量名来使用变量值,是使用和被使用的关系
变量名的规范
注意,变量名后面的等号左右不能有空格,这和其他语言不一样。
变量名的命名规范:
命名只能使用英文字母、数字和下划线,首个字符不能以数字开头。
中间不能有空格,可以有下划线。
不能使用标点符号。
不能使用bash里的关键字(可用help命令查看保留关键字)
案例1:使用变量改写入门脚本中的第一个shell脚本。
#!/bin/bash
str='hello world'
echo $str
调试
[root@xia /]# vim test3.sh
[root@xia /]# chmod +x test3.sh
[root@xia /]# ./test3.sh
hello world
关于单双引号问题:
双引号能够识别变量,双引号能够实现转义(类似于"*")单引号是不能识别变量,之后原样输出,单引号是不能转义的。
案例2:定义一个变量,输出当前的时间按,要求格式为”年-月-日 时:分:秒“
#!/bin/bash
sj=`date +"%F %T"`
echo $sj
[root@xia /]# chmod +x test4.sh
[root@xia /]# ./test4.sh
2021-08-12 19:20:08
注意:反引号,当在脚本中需要执行一些指令并且将执行的结果赋给变量的时候需要使用“反引号”。
1.3、只读变量(了解)
语法:readonly 变量名
案例:定义变量a并且其值为10,随后设置成只读变量,再尝试去赋值
#!/bin/bash
a=10
readonly a
a=20
echo $a
[root@xia /]# chmod +x test5.sh
[root@xia /]# ./test5.sh
./test5.sh: line 4: a: readonly variable
10
接收用户输入(重点)
语法:read -p 提示信息 变量名
案例:编写脚本test6.sh,要求执行之后提示用户输入文件的名称(路径),然后自动为用户创建该文件
#!/bin/bash
read -p 'dd' filep
touch $filep
ls -l $filep
[root@xia ~]# ./test6.sh
bash: ./test6.sh: Permission denied
[root@xia ~]# chmod +x test6.sh
[root@xia ~]# ./test6.sh
dd/root/xx.txt
-rw-r--r-- 1 root root 0 Aug 12 20:00 /root/xx.txt
1.5、删除变量
语法:unset 变量名
案例:创建两个变量输出,然后删除其中一个再输出,查看变化。
#!/bin/bash
a=123
b=2
echo $a $b
unset a //此处不用$符号
echo $a $b
[root@xia ~]# chmod +x test5.sh
[root@xia ~]# ./test5.sh
123 2
2
2、条件判断语句
老婆给当程序员的老公打电话,下班顺路买一斤包子带回来,如果看到卖西瓜的,买一个。当晚程序员老公手捧一个包子进了家门...老婆怒道:你怎么就买了一个包子?老公答:因为看到卖西瓜的了。
语法1:
if condition
then
command1
command2
...
fi //结束
单行语法:if[condition];then command; fi
语法2:
if condition
then
command1
command2
...
else
command
fi
语法3:
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
3、运算符
在shell中,运算符和其他编程脚本语言一样,常见的有算数运算、关系运算、逻辑运算、字符串运算、文本测试运算等。
3.1、算数运算符
下表列出了常用的算数运算符,假定变量a=10 b=20
注意:条件表达式要放在方括号中,并且要有空格,例如:[$a == $b]是错误的,必须写成[ $a == $b ]。
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如awk和expr,expr最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
例如,两个数相加(注意使用的是反引号`而不是单引号)
#!/bin/bash
a=123
b=2
val=`expr $a + $b` //表达式和运算符之间要有空格,用反单引号包起来
echo $val //要用变量的值,前面使用$符
[root@xia ~]# chmod +x test5.sh
[root@xia ~]# ./test5.sh
125
3.2、关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
下表列出了常用的关系运算符,假定变量a=10 b=20
-eq:equal //判断是否相等
-ne:not equal &emap;//判断是否不相等
-gt:great than &emap;//判断左边的是否大于右边的
-lt:less than &emap;//判断左边的是否小于右边的
-ge:great than or equal &emap;//判断左边的是否小于等于右边的
-le:less than or equal &emap;//判断右边的是否大于等于右边的
#!/bin/bash
a=10
b=20
echo "a = $a"
echo "b = $b"
echo
if [$a -eq $b]
then
echo 'a = b'
else
echo 'a no b'
fi
3.3、逻辑运算符
列出常用的布尔运算符,假定a=10 b=20
或运算:一个为真即为真,全部为假才是假
与运算:全部为真才为真,全部为真才是真
非运算:非真为假,非假为真
#!/bin/bash
a=10
b=20
if [ !false ]
then
echo 'zhen'
fi
if [ $a -lt 20 -o $b -gt 100 ]
then
echo 'zhen'
fi
[root@xiaxiangming ~]# chmod +x test.sh
[root@xiaxiangming ~]# ./test.sh
zhen
zhen
3.4、字符串运算符
下表列出了常用的字符串运算符,假定变量a="abc" b="efg"
案例:验证
#!/bin/bash
a='abc'
b='efg'
if [ $a = $b ]
then
echo 'ture'
else
echo 'false'
fi
if [ $a != $b ]
then
echo 'ture'
else
echo 'false'
fi
[root@xia ~]# ./test.sh
false
ture
3.5、文件测试运算符(重点)
文件测试运算符用于检测unix/linux文件的各种属性。
属性检测描述如下:
案例:验证。
#!/bin/bash
filepath='/root/aa.txt'
dirpath='/root/Desktop'
if [ -d $dirpath ]
then
echo 'true'
else
echo 'flase'
fi
if [ -r $filepath ]
then
echo 'true'
else
echo 'flase'
fi
if [ -w $filepath ]
then
echo 'true'
else
echo 'flase'
fi
if [ -x $filepath ]
then
echo 'true'
else
echo 'flase'
fi
[root@xia ~]# ./test.sh
true
true
true
flase
4、shell脚本附带选项(重点)
问题描述:在Linux shell 中如何处理tail -n 10 access.log这样的命令行选项?
调用tail指令,把后续选型传递给tail,tail先去打开指定的文件,取出最后10行。
问题:我们自己写的shell是不是也像内置命令一样传递一些选项那?
答:可以的,传递方式和上述的描述是一样的。关键是怎么接收的。例如:
传递:
./test.sh 1 2 3
接收:
在脚本中用“$1”来表示1,用“$2”来表示2,用“$3”来表示3依次类推。
接收可以用'$'加上选项对应的数字即可。
测试:编写test.sh,传递a,b,c输出其值
#!/bin/bash
echo $0 $1 $2 $3
[root@xia ~]# ./test.sh 1 2 3
1 2 3
其实$1,$2是变量
练习:创建自定义指令“user”,可以直接执行,要求该指令具备以下语法和功能:
a.#user -add 用户名 &emap; [添加用户]
b.#user -del 用户名 &emap; [删除用户及其家目录]
#!/bin/bash
if [ $1 = '-add' ]
then
useradd $2
else
userdel -r $2
fi
[rootexia~]#./test.sh -add root1
[rootexia~]# tail-1 /etc/passwd
root1:x:1001:1001::/home/root1:/bin/bash
[root@xia~]#./test.sh -del root1
[rootexia~]#
题目要求是指令,故添加一个别名:
#vim ~/.bashrc
[root@xia ~]# user -add xia