从操作系统层面来说,shell是一个“壳”,人机交互接口,实质上shell就是命令解释器,解析用户输入的命令,进而达到人机交互的功能
bash编程语言属于弱类型编程语言,不区分数据类型,所有数据默认当做字符处理,若要做运算处理,则需要使用算术表达式,同时也是过程式编程语言,以指令为中心,围绕指令设计数据
过程式编程语言:
顺序执行
选择执行
循环执行
shell编程本质:语法结构+命令堆积
脚本编写:
首行定顶格给出shebang(这是个固定格式)
#!/bin/bash
#!/bin/bash
#!/bin/tcsh
#!/usr/bin/python3
#!/usr/bin/perl
给出任意一个就行,基于所使用的shell类型
#号表示注释信息,不会当做命令行处理
操作系统:CentOS Linux release 7.2.1511 (Core)
内核版本:3.10.0-327.10.1.el7.x86_64
运算表达式:
let name=$[算术表达式]
let name=$((算术表达式))
图例:
逻辑运算:
与运算:command1 && command2
真 && 真 = 真
真 && 假 = 假
假 && 真 = 假
假 && 假 = 假
总结:真真才为真,有假必假
图例:与运算,若前面命令执行成功则为真,后面命令执行,若前面命令执行失败则为假,则后面命令不执行
或运算:command1 || command2
真 || 真 = 真
真 || 假 = 真
假 || 真 = 真
假 || 假 = 假
总结:有真必真,假假才假
图例:或运算,若前面命令执行成功则为真,后面命令不执行,若前面命令执行失败则为假,后面命令执行
非运算:!command(叹号取反)
!真 = 假
!假 = 真
三种运算的优先级区分:与>或>非
图例:取反只是取反命令的执行状态,echo $? 的返回值,命令执行本身实则执行成功
命令执行状态:
0:执行成功
1-255:执行失败(非零)
注意,当命令作为条件判断时,引用的是命令的执行状态,即命令执行成功与否
位置参数变量:手动传递参数给脚本
在bash脚本中,给出一个或多个变量参数:
$1:第一个参数
$2:第二个参数
$3:第三个参数
...
在执行脚本时手动添加参数,多个参数之间以空格隔开
例如:#!/bin/bash
echo $1
echo $2
图例:
特殊变量:
$0 脚本文件路径自身
$# 表示脚本参数的个数
$*,$@:引用所有的位置参数
测试表达式:
test 测试表达式
[ 测试表达式 ]
[[ 测试表达式 ]]
注意,括号和表达式之间有空格隔开
数值测试:
-eq:是否等于
-ne:是否不等于
-gt:是否大于
-ge:是否大于等于
-lt:是否小于
-le:是否小于等于
图例:设定两个变量num1和num2,测试num1是否大于num2,大于则为真,反之则为假
字符测试:[[ ]]
-z:字符是否为空,空则真
-n:判断字符是否不为空
==:是否等于
=~:是否包含
>:是否大于
<:是否小于
!=:是否不等于
示例:查看主机名是否包含linux字符串
文件测试:
单目测试:
文件是否存在:
-e file 文件存在,则为真
-a file 同-e
文件类型测试:
-f file 是否为普通文件
-b file 是否为块设备
-c file 是否为字符设备
-d file 是否为目录
-h/-L file 是否为连接符号
-p file 是否为管道设备
-s file 是否为套接字设备
文件权限测试:
-r file 当前文件是否存在并当前用户是否有读权限
-w file 当前文件是否存在并当前用户是否有写权限
-x file 当前文件是否存在并当前用户是否有执行权限
从属关系测试:
-O file 当前用户是否为文件属主
-G file 当前用户是否为文件属组
时间戳测试:
-N file 文件自从上次操作后是否被改过
双目测试:
file -ef file2 是否指向同一个文件系统的相同inode的硬链接
file -nt file2 file文件是否新于file2
file -ot file2 file文件是否旧于file2
条件判断:
单分支:
if 条件;then
执行分支1
双分支:
if 条件;then
执行分支1
else
执行分支2
多分支:
if 条件;then
执行分支1
elif 条件2;then
执行分支2
...
else
执行分支n
交互式脚本:
read [-p|-t] "words" VARNAME . . .
图例:
for循环:
语法:
for VAR_ANME in value1 value2 value3 ...; do
COMMAND... 变量引用
done
( 红色标记为固定语法结构)
例:添加10个用户suer1-user10
for num in {1..10}; do
useradd user$num
done
列表方法:
{1..10}=1 2 3 4 5 6 7 8 9 10
seq 起始数 步长 结束数
seq 1 2 9=1 3 5 7 9
for循环,把变量名所对应的变量列表进行遍历
练习:
1.写一个脚本,分别计算
(1) /etc/passwd 文件中 第15个用户和第18个用户的ID号之和
(2)/etc/rc.d/init.d/functions 和 /etc/rc.d/init.d/network 文件的空白行数之和
2.写一个脚本,完成如下功能,判断给定的两个数值,谁大谁小, 使用位置参数和命令交互
3写一个脚本,提示用户输入一个字符串,如果输入的是quit,则退出,否则,显示其输入的字符串内容。
4.用户for循环将/etc/passwd的第3,7,11个用户的用户名和id显示出来
5.写一个脚本,用户for循环实现
显示、/etc/init.d/functions、 /etc/rc.d/rc.local和/etc/fstab各有多少行
6.将上题中三个文件复制到/tmp目录下,分别将每个文件的最近一次修改时间改为2011年9月15号13点27分,用for循环实现
7.通过命令参数,给定两个数字,输出其中最大的数字,若数字相同,则提示相同,若参数超过两个,则报错退出。
8.写一个脚本,该脚本可以一次性添加3名用户,通过传参数的方式,进行用户名添加,当传递的参数不符合3个的时候,报错并退出,当传递完成后,输出哪些用户被进行了添加。当三名用户添加完成后,将本脚本权限改成属主可读可写可执行
9. 判断,/etc/passwd 是否为文件,如果为文件,则输出 /etc/passwd is files ,该路径通过命令传递的方式传入,当传入的参数个数大于1 ,则报错
10.通过命令行参数,给定两个文本文件名,如果某文件不存在,则结束脚本执行,若都存在时,返回每个文件的行数,并echo出其中行数较多的文件名
11.背景:公司来了个新员工,需要给新员工开通帐号和统计出新员工的信息(通过交互的方式)
让用户指定一个用户名和密码,若用户名之前存在,先进行删除。之后则为用户添加系统帐号。
完成后,需要统计员工的:手机号,email,QQ号,年龄信息,收集后存储到该用户的家目录中。
完成以上操作,询问该用户,是否需要给用户单独建立一个工作目录为/data/username,默认是需要,如果不需要,则需输入n或者N
不正之处,欢迎指教
--end