一句话来概括shell
shell是一个基于Linux内核和应用程序之间的一个解释器
Shell解释器
/bin/sh
/bin/bash 目前多用的是bash
/sbin/nologin
/bin/dash
/bin/tcsh
/bin/csh
Shell的编程语言:
编写第一个shell脚本
1.删除class21下的test文件夹
2.在class21新建一个文件夹test2,在test2中创建3个子文件夹dir1,dir2,dir3
3.在dir2中新建一个文件student.txt
4.在student.txt中添加一个zhangsan
5.打印“任务执行完毕,2019-12-14 09:32:00”
#!/bin/env bash
:<<EOF
多行注释
jbckaslsjbcjk
EOF
:<<!
多行注释
asbc
!
#1.删除class21下的test文件夹
rm -rf /root/shell_class21/test
#2.在class21新建一个文件夹test2,在test2中创建3个子文件夹dir1,dir2,dir3
mkdir -p /root/shell_class21/test2/dir{1..3}
#3.在dir2中新建一个文件student.txt
cd /root/shell_class21/test2/dir2
touch student.txt
#4.在student.txt中添加一个zhangsan
echo "张三" >> student.txt
#5.打印“任务执行完毕,2019-12-14 09:32:00”
echo "任务执行完毕 `date "+%Y-%m-%d %H:%M:%S"`"
编写脚本:
1.#!/bin/env bash 或者 #!/bin/bash
2.添加脚本的描述信息(姓名、描述、路径、创建日期、更新日期等)
3.开始写脚本
执行脚本:
bash + 相对路径
bash + 绝对路径
sh + 相对路径
sh + 绝对路径
source + 绝对路径
推荐的执行方式:(相对路径、绝对路径执行)
1.为脚本添加可执行的权限
chmod +x 脚本名称.sh
2.相对路径(在脚本所在的文件夹下)
./脚本名称.sh
3.绝对路径执行
/root/class21/脚本名称.sh
注意:
脚本中的第一行,指明解释器,一定不要写错
扩展命令
bash -n 脚本名称.sh #查找脚本的语法错误
bash -x 脚本名称.sh #查看脚本的执行过程
变量
1.系统变量
2.自定义变量
int a = 1;
shell中的变量
a=1 #注意变量等号左右两边不要出现空格;变量名不要包含特殊字符;变量名称不能以数字开头
#作用域:只针对当前用户和当前会话有效
echo $a 或者 echo ${a} #读取变量
export b=2 #(全局环境变量)作用域:只针对当前会话的所有用户有效
创建系统的环境变量(作用域:只针对所有会话的所有用户有效)
1.vim /etc/profile
2.创建变量
export 变量名(大写)=变量的值
3.激活
source /etc/profile
取消变量
unset a
创建只读变量
readonly 变量名=值
特殊变量 $n、$#、$*、$@、$?
#!/bin/bash
echo $0 $1 $2 $3 ${11}
echo $0 $1 $2 $3 ${11}
echo $#
echo $*
echo $@
for i in "$*"
do
echo $i
done
for i in "$@"
do
echo $i
done
echo $? 返回结果0:表示成功 1:表示失败
==============================数组======================================
java
String[] fileds={"1","2",.....}
for(int i=0;i<fileds.lenght;i++){
sout(fileds[i])
}
shell
创建空数据
arr1=()
创建非空数据(元素以空格分割)
arr1=(1 2 3 4 5)
根据索引给数组赋值
arr[1]=元素值
获取数组中的某个元素
${arr1[1]}
获取数组中的所有元素
${arr1[*]} ${arr1[@]}
获取数组的长度
${#arr1[*]} ${#arr1[@]}
arr1=(a b c d e "hello word")
for i in ${arr1[@]}
do
echo $i
done
==========================运算===========================
+ , - , *, /, % 加,减,乘,除,取余
echo $(($b+$a)) <=> echo $[$b+$a]
echo $[(2+3)*4]
+ , - , *, /, % 加,减,乘,除,取余
expr $b + $a
expr `expr 2 + 3 ` * 4
小数之间的运算(scale 小数点后几位,只对除法有效)
echo $(echo "scale=1; $c*$b" | bc)
==========================条件判断====================
2. 常用判断条件
(1)两个整数之间比较
= 字符串比较
-lt 小于(less than) -le 小于等于(less equal)
-eq 等于(equal) -gt 大于(greater than)
-ge 大于等于(greater equal) -ne 不等于(Not equal)
a=3
b=4
例如:[ $a -lt $b ]
(2)按照文件权限进行判断
-r 有读的权限(read) -w 有写的权限(write)
-x 有执行的权限(execute)
例如:[ -x 文件名 ]
(3)按照文件类型进行判断
-f 文件存在并且是一个常规的文件(file)
-e 文件存在(existence) -d 文件存在并是一个目录(directory)
例如:[ -e 文件名 ]
if 流程控制语句
java
if
int a=3;
if(a==3){
sout(...)
}else if{
sout(...)
}
else{
sout(...)
}
shell
如果aaa.txt文件存在,往文件中写入bbb,如果不存在,创建aaa.txt文件,往文件中写入bbb
if [ -f aaa.txt ]
then
echo "该文件存在"
echo "bbb" >> aaa.txt
else
echo "该文件不存在"
touch aaa.txt
echo "bbb" >> aaa.txt
fi
if 判断
1.基本语法
if [ 条件判断式 ];then
程序
fi
或者
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
注意事项:
(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
(2)if后要有空格
if [ 条件判断式 ];then
程序
fi
或者
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
注意:if和elif后需要有空格
case 语句
1.基本语法
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
注意事项:
1) case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
2) 双分号“;;”表示命令序列结束,相当于java中的break。
最后的“*)”表示默认模式,相当于java中的default。
case流程控制语句
java:
int a=111;
switch(a){
case 111:
sout(...);
break;
case 222:
sout(...);
break;
default:
sout(...);
break;
}
shell
使用case判断输入内容,如果输入1,输出aaa,如果输入2,输出bbb,如果输入其他,输出ccc
case $1 in
"1")
echo "aaa"
;;
"2")
echo "bbb"
;;
*)
echo "ccc"
;;
esac
注意:case 相当于java中的switch
"1") 相当于switch 中的 case "1":
*) 相当于switch 中的default
;; 相当于switch 相当于break
结尾 esac
for 循环
1.基本语法1
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
for循环语句
for 计算1到100之间所有偶数的和
#!/bin/bash
:<<!
计算1到100之间所有偶数的和
!
sum=0
for((i=1;i<=100;i++))
do
if [ $(($i%2)) -eq 0 ]
then
sum=$[$sum+$i]
fi
done
echo "计算完毕$sum"
while循环语句
while
i=1
sum=0
while [ $i -le 100 ]
do
if [ $(($i%2)) -eq 0 ]
then
sum=$[$sum+$i]
fi
i=$[$i+1]
done
echo $sum
注意:while后边有空格
read
1.基本语法
read(选项)(参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数
变量:指定读取值的变量名
read:
read -t 5 -p "请在5秒之内输入要计算的数字(偶数)的和" NUM
echo $NUM
//判断事否输入了变量
if [ ! -n "$NUM" ]
then
echo "用户没有输入数字"
exit;
fi
系统函数basename、dirname
[root@jinghang01 shell_class21]# basename /root/shell_class21/shell08_while.sh
shell08_while.sh
[root@jinghang01 shell_class21]# basename /root/shell_class21/shell08_while.sh .sh
shell08_while
[root@jinghang01 shell_class21]# dirname /root/shell_class21/shell08_while.sh
/root/shell_class21
自定义函数
一种是带参数
function 函数名(){
s=0
s=$[$1+$2]
echo $s
}
调用
函数名 $1 $2
一种是不带参数
function 函数名(){
s=0
s=$[1+2]
echo $s
}
调用
函数名
带返回值的函数,返回值只能是数子,并且数字只能再0~255之间,
function aa() { echo "aaaaa"; return 2}
调用
aa
通过执行echo $?可以获取返回值
作业练习:
1.写一个脚本输入任意数组或则数字例如 2 3 4 5 6 7 8 9,输出最大值、最小值、平均值
#!/bin/bash
min=$1
max=$1
sum=0
for i in "$@"
do
if [ $min -gt $i ]
then
min=$i
fi
if [ $max -lt $i ]
then
max=$i
fi
sum=$[$sum+$i]
done
echo "最大值为" $max
echo "最小值为" $min
echo "平均值为" $[$sum/$#]
2.写一个脚本输入任意数组或则数字例如 2 4 3 5 9 7 8 6,按照从小到大排序后输出
#!/bin/bash
arr=()
i=0
for value in "$@"
do
arr[$i]=$value
i=$[$i+1]
done
echo ${arr[*]}
for ((i=0;i<${#arr[@]};i++))
do
for ((j=$i;j<${#arr[@]};j++))
do
tmpvalue=${arr[$i]}
if [ ${arr[$j]} -lt $tmpvalue ]
then
arr[$i]=${arr[$j]}
arr[$j]=$tmpvalue
fi
done
done
echo ${arr[@]}
3.完成/root/shell_test/文件夹下完成一个脚本
1.判断aaa.txt文件是否存在,存在则往文件中写入bbb,如果不存在,创建aaa.txt文件,往文件中写入bbb
2.每一分钟执行一次脚本
shell中文本处理工具
cut
[root@jinghang01 shell_class21]# cat if | grep Bcast
inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
[root@jinghang01 shell_class21]# cat if | grep Bcast | cut -d : -f 1
inet addr
[root@jinghang01 shell_class21]# cat if | grep Bcast | cut -d : -f 1,2
inet addr:192.168.1.100 Bcast
[root@jinghang01 shell_class21]# cat if | grep Bcast | cut -d : -f 2
192.168.1.100 Bcast
[root@jinghang01 shell_class21]# cat if | grep Bcast | cut -d : -f 2 | cut -d " " -f 1
192.168.1.100
[root@jinghang01 shell_class21]# cat if | grep Bcast | cut -d : -f 2 | cut -d " " -f 2
[root@jinghang01 shell_class21]# cat if | grep Bcast | cut -d : -f 2 | cut -d " " -f 3
Bcast
[root@jinghang01 shell_class21]# cat if | grep Bcast | cut -d : -f 2 | cut -d " " -f 1
192.168.1.100
[root@jinghang01 shell_class21]# cat if | grep Bcast | cut -d : -f 2 | cut -d " " -f 1 | cut -c 1-3
192
[root@jinghang01 shell_class21]# cat if | grep Bcast | cut -d : -f 2 | cut -d " " -f 1 | cut -c 1,3
12
sed
选项参数 功能
-e 直接在指令列模式上进行sed的动作编辑(一次执行多个操作时)。
-i 直接编辑文件
命令功能描述
命令 功能描述
a 新增,a的后面可以接字串,在下一行出现
d 删除
s 查找并替换
awk
正则表达式
. 匹配除了换行符之外的任意字符
d 匹配数字0-9 => [0-9]
D 匹配非数字 => [^0-9]
s 匹配空白字符(空格
....)
S 匹配非空白字符
w 匹配单词字符([a-zA-Z0-9_])
W 匹配非单词字符
^ 匹配以...开头
$ 匹配结尾
多字符匹配(贪婪匹配)
.* 匹配*号前的字符任意次数 aaabbbccc a*?
.+ 匹配+号前的字符至少一次
.? 匹配?号前的字符0~1次
多字符匹配(非贪婪匹配)
.*?
.+?
.??
其他
|
() 分组
命令:
cat passwd | awk -F : '/^root/{print $1"-"$3}'
结果:
root-0
cat passwd | awk -F : '/^root|^jinghang/{print $1"-"$3}'
root-0
jinghang-500
cat passwd | awk -F : '/^root/{print $1"-"$3} /^jinghang/{print $1"-"$3}'
root-0
jinghang-500
awk -F : 'BEGIN{sum=0}{sum+=1;print $1","sum}END{print sum}' passwd
awk -F : '$3 > 100' passwd
awk -v sum=0 -F : '{sum+=1;print $1","sum}END{print sum}' passwd
awk内置变量的使用
FILENAME 文件名
NR 已读的记录数
NF 浏览记录的域的个数(切割后,列的个数)
awk -F : '{print "filename:"FILENAME",lines:"NR",colums:"NF}' passwd
使用awk提取ip地址
cat if | grep Bcast | awk -F : '{print $2}' | awk -F " " '{print $1}'
获取文件空行的行号
cat if | awk '/^$/{print NR}'
获取文件空行的总行数
cat if | awk '/^$/{print NR}' | wc -l
sort
-n 依照数值的大小排序
-r 以相反的顺序来排序
-t 设置排序时所用的分隔字符
-k 指定需要排序的列
sort -t : -k 3 -n passwd 升序
sort -t : -k 3 -nr passwd 降序
晚上作业(允许百度)
1.判断/root/class21/inittab.txt文件是否大于100行,如果大于,则显示”inittab is a big file.”否者显示”inittab is a small file.”
line='wc -l /etc/inittab/cut -d'' -f1'
if [ $line -gt 100 ];
then
echo"/etc/inittab is a big file"
else
echo"/etc/inittab is a small file"
fi
2.写出一个脚本程序,给定一个文件,比如:/root/class21/inittab.txt a、判断这个文件中是否有空白行? b、如果有,则显示其空白行的总行数,否则显示没有空白行
#!/bin/bash
#
B=`grep -n "^[[:space:]]*$" /etc/inittab|wc -l`
C=`grep -n "^[[:space:]]*$" /etc/inittab|cut -d: -f1`
if[$B -eq 0];then
echo"没有空白行"
else
echo"有空白行,空白行为$C行"
3.给定一个文件,如果是普通文件,就显示出来,如果是目录文件,也显示出来,否则就显示“无法识别”
#!/bin/bash
read -t 5 -p "请输入一个文件:" filename //-t 等待时间
echo #默认用来换行
if [-z $filename];then
echo"eg./etc/fstab"
exit 8
fi
if [-f $filename];then
echo"$filename是一个普通文件"
exit 0
elif [-d $filename];then
echo"$filename是一个目录文件"
exit 0
else
echo"无法识别"
exit 1
fi
4.写一个脚本,给脚本传递3个参数 两个数字,一个运算符,根据运算符计算出结果,例如 2 3 - 2-3=1
5.使用脚本批量创建用户
#!/bin/bash
i=1
groupadd group1
while [ $i -le 30 ]
do
if [ $i -le 9 ] ; then
username=user0$i
else
username=user$i
fi
useradd $username
mkdir /home/$username
chown -R $username /home/$username
chgrp -R group1 /home/$username
i=$(($i+1))
done