shell概述
shell是命令行解释器,接受外层应用程序、用户的命令然后调用操作系统的内核,最终控制硬件
[root@yangdong ~]# cat /etc/shells /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash /bin/tcsh /bin/csh
sh是bash的软连接,sh调用的是bash
[root@yangdong ~]# cd /bin [root@yangdong bin]# ll|grep bash -rwxr-xr-x. 1 root root 964600 8月 8 2019 bash lrwxrwxrwx. 1 root root 10 4月 3 12:30 bashbug -> bashbug-64 -rwxr-xr-x. 1 root root 6964 8月 8 2019 bashbug-64 lrwxrwxrwx. 1 root root 4 4月 3 12:30 sh -> bash
bash解析shell文本
[root@yangdong bin]# echo $SHELL /bin/bash
shell脚本入门
脚本格式
脚本以#!/bin/bash开头(指定解析器)
#!/bin/bash echo "hello world"
shell脚本的后缀名是.sh
执行shell脚本使用命令bash/sh XXX.sh可以借助bash直接执行
也可以赋予执行权限后使用./执行
使用sh/bash执行脚本本质是bash解析器帮你执行脚本,所以脚本不需要执行权限
./本质是脚本需要自己执行,所以需要执行权限
[root@yangdong shelltest]# vim frist [root@yangdong shelltest]# sh frist.sh sh: frist.sh: 没有那个文件或目录 [root@yangdong shelltest]# mv frist frist.sh [root@yangdong shelltest]# sh frist.sh hello world [root@yangdong shelltest]# ./frist.sh -bash: ./frist.sh: 权限不够 [root@yangdong shelltest]# chmod 777 frist.sh [root@yangdong shelltest]# ./frist.sh hello world
多命令处理
#!/bin/bash cd /shelltest touch banzhang.txt echo "i love cls">>banzhang.txt
[root@yangdong shelltest]# vim batch.sh [root@yangdong shelltest]# bash batch.sh [root@yangdong shelltest]# cat banzhang.txt i love cls
shell中的变量
常用系统变量
$HOME $PWD $SHELL $USER
[root@yangdong shelltest]# echo $HOME /root [root@yangdong shelltest]# echo $PWD /shelltest [root@yangdong shelltest]# echo $SHELL /bin/bash [root@yangdong shelltest]# echo $USER root
自定义变量
[root@yangdong shelltest]# A=1 [root@yangdong shelltest]# echo $A 1
删除自定义变量
[root@yangdong shelltest]# unset A [root@yangdong shelltest]# echo $A
声明静态变量 readonly,不能unset
[root@yangdong shelltest]# readonly B=3 [root@yangdong shelltest]# echo $B 3 [root@yangdong shelltest]# unset B -bash: unset: B: 无法反设定: 只读 variable
环境变量名建议大写
等号两边不能有空格
在bash中变量默认都是字符串类型,无法直接进行数值运算
[root@yangdong shelltest]# C=1+1 [root@yangdong shelltest]# echo $C 1+1
变量的值如果有空格需要使用单引号或者双引号括起来
[root@yangdong shelltest]# D= banzhang love mm bash: banzhang: 未找到命令... [root@yangdong shelltest]# D=" banzhang love mm " [root@yangdong shelltest]# echo $D banzhang love mm
可以把变量提升为全局变量,可供其他shell程序使用
在frist.sh文件中添加echo $D
#!/bin/bash echo "hello world" echo $D
[root@yangdong shelltest]# ./frist.sh hello world [root@yangdong shelltest]# echo $D banzhang love mm
export D把D提升为全局变量
[root@yangdong shelltest]# export D [root@yangdong shelltest]# ./frist.sh hello world banzhang love mm
特殊变量
$n(n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,第十个以上的参数使用{}${10})
#!/bin/bash echo "$0 $1 $2 $3"
[root@yangdong shelltest]# sh parameter.sh parameter.sh [root@yangdong shelltest]# sh parameter.sh banzhang parameter.sh banzhang [root@yangdong shelltest]# sh parameter.sh banzhang love parameter.sh banzhang love [root@yangdong shelltest]# sh parameter.sh banzhang love mm parameter.sh banzhang love mm [root@yangdong shelltest]# sh parameter.sh banzhang love mm hehe parameter.sh banzhang love mm
$#(获取所有输入参数个数,常用于循环)
#!/bin/bash echo "$0 $1 $2 $3" echo $#
[root@yangdong shelltest]# sh parameter.sh banzhang love mm hehe parameter.sh banzhang love mm 4 [root@yangdong shelltest]# sh parameter.sh banzhang love mm parameter.sh banzhang love mm 3
$*(命令行中所有参数,$*把所有参数看成一个整体)
$@(命令行中所有参数,$@把每个参数区分对待)
#!/bin/bash echo "$0 $1 $2 $3" echo $# echo $* echo $@
root@yangdong shelltest]# sh parameter.sh banzhang love mm parameter.sh banzhang love mm 3 banzhang love mm banzhang love mm [root@yangdong shelltest]# sh parameter.sh 1 2 3 4 parameter.sh 1 2 3 4 1 2 3 4 1 2 3 4
$?(描述最后一次执行命令的返回状态。返回0证明上一次命令正确执行,非0证明上一个命令执行不正确)
[root@yangdong shelltest]# echo $? 0
运算符
基本语法
"$((运算式))"或者"$[运算式]"
expr + - \* / %
[root@yangdong shelltest]# expr 3+2 3+2 [root@yangdong shelltest]# expr 3 + 2 5 [root@yangdong shelltest]# expr 3 +2 expr: 语法错误 [root@yangdong shelltest]# s=$[(2+3)*4] [root@yangdong shelltest]# echo $s 20
条件判断
[ condition ]condition前后要有空格,条件非空返回true,[]返回false
[root@yangdong shelltest]# [ 23 -gt 22 ] [root@yangdong shelltest]# echo $? 0 [root@yangdong shelltest]# [ 23 -le 22 ] [root@yangdong shelltest]# echo $? 1 [root@yangdong shelltest]#
常用判断条件
= 字符串比较
-lt 小于(less than)
-le小于等于(less equal)
-eq等于(equal)
-gt大于(greater than)
-ge大于等于(greater equal)
-ne 不等于(not equal)
文件权限判断
-r可读(read)
-w 可写(write)
-x可执行(execute)
[root@yangdong shelltest]# [ -w frist.sh ] [root@yangdong shelltest]# echo $? 0 [root@yangdong shelltest]# [ -x frist.sh ] [root@yangdong shelltest]# echo $? 0
文件类型判断
-f文件存在并且是一个常规文件(file)
-e文件存在(existence)
-d文件存在并且是一个目录(directory)
[root@yangdong shelltest]# [ -e frist.sh ] [root@yangdong shelltest]# echo $? 0 [root@yangdong shelltest]# [ -f frist.sh ] [root@yangdong shelltest]# echo $? 0 [root@yangdong shelltest]# [ -d frist.sh ] [root@yangdong shelltest]# echo $? 1
多条件判断
&&表示前一条命令执行成功时才执行后一条命令
||上一条命令执行失败后才执行下一条命令
[root@yangdong shelltest]# [ condition ]&&echo ok||echo notok ok [root@yangdong shelltest]# [ condition ]&&[]||echo notok bash: []: 未找到命令... notok
流程控制
if语法
if [ 条件判断式 ];then
程序
fi
if [ 条件判断式 ]
then
程序
fi
注意事项:
[ 条件判断式 ],中括号和条件判断式之间必须有空格
if后要有空格
#!/bin/bash if [ $1 -eq 1 ] then echo "bzzs" elif [ $1 -eq 2 ] then echo "clszm" fi
[root@yangdong shelltest]# sh second.sh 1 bzzs [root@yangdong shelltest]# sh second.sh 2 clszm
case语法
case $变量名 in
"值 1")
如果变量的值等于值1,则执行程序1
;;
"值 2")
如果变量的值等于值2,则执行程序2
;;
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
case行尾必须为单词in,每一个模式匹配必须以右括号“)”结束
双分号“;;”表示命令序列结束,相当于java的break
*)表示默认模式,相当于java的default
#!/bin/bash case $1 in 1) echo "banzhang" ;; 2) echo "cls" ;; *) echo "renyao" ;; esac
[root@yangdong shelltest]# sh case.sh 2 cls [root@yangdong shelltest]# sh case.sh 3 renyao [root@yangdong shelltest]# sh case.sh 1 banzhang
for语法
for(( 初始值;循环控制条件;变量变化))
do
程序
done
#!/bin/bash s=0 for((i=1;i<=100;i++)) do s=$[ $s+$i ] done echo $s
[root@yangdong shelltest]# sh for.sh 5050
for i in $*/$@
do
程序
done
#!/bin/bash for i in $* do echo "cls love $i" done
[root@yangdong shelltest]# sh forin.sh banzhang lala lili lily cls love banzhang cls love lala cls love lili cls love lily
while语法
while [ 条件判断式 ]
do
程序
done
#!/bin/bash s=0 i=1 while [ $i -le 100 ] do s=$[$s+$i] i=$[$i+1] done echo $s
[root@yangdong shelltest]# sh while.sh 5050
read读取控制台输入
read语法
read(选项)(参数)
选项
-p 指定读取值时的提示符
-t 指定读取值时等待的时间
参数
变量:指定读取值时的变量名
#!/bin/bash read -t 10 -p "请输入你的名字在10秒之内" NAME echo $NAME
[root@yangdong shelltest]# sh read.sh 请输入你的名字在10秒之内111111111111 111111111111
函数
系统函数
basename:截取路径生成文件名
[root@yangdong shelltest]# basename /shelltest/while.sh while.sh [root@yangdong shelltest]# basename /shelltest/while.sh .sh while
dirname:截取文件绝对路径
[root@yangdong shelltest]# dirname /shelltest/while.sh /shelltest
自定义函数
基本语法
[ function ] funname[()]
{
Action;
[return int;]
}
funname
必须在调用函数地方之前先声明函数,shell脚本是逐行运行,不会像其他语言一样先编译
函数返回值只能通过$?系统变量获得,可以显示加return返回,如果不加将以最后一条命令运行结果作为返回值,return后跟数值n(0-255)
#!/bin/sh function sum(){ s=0; s=$[ $1+$2 ] echo $s } read -p "请输入参数1:" P1 read -p "请输入参数2:" P2 sum $P1 $P2
[root@yangdong shelltest]# sh sum.sh 请输入参数1:3 请输入参数2:4 7
shell工具
cut:在文件中负责剪切数据,从文件中的每一行剪切字节,字符,字段,并将这些字节字符字段输出
cut [选项参数] filename
默认分隔符是制表符
-f 列号,提取第几列
-d 分隔符,按照指定分隔符分割列
dong shen guan zhen wo wo lai lai le le
[root@yangdong shelltest]# cut -d " " -f 2 cut.txt shen zhen wo lai le [root@yangdong shelltest]# cut -d " " -f 1 cut.txt dong guan wo lai le
dong shen guan zhen wo wo lai lai le le [root@yangdong shelltest]# cut -d " " -f 2,3,4,5 cut.txt shen zhen wo lai le [root@yangdong shelltest]# cat cut.txt | grep guan guan zhen [root@yangdong shelltest]# cat cut.txt | grep guan | cut -d " " -f 1 guan 选取系统PATH变量值第二个“:”开始后的所有路径 [root@yangdong shelltest]# echo $PATH /usr/local/libexec/git-core:/usr/local/bin:/opt/apache-maven-3.6.3/bin:/opt/jdk1.8.0_141/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin [root@yangdong shelltest]# echo $PATH | cut -d : -f 3- /opt/apache-maven-3.6.3/bin:/opt/jdk1.8.0_141/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
sed流编辑器,一次处理一行内容,处理时把当前处理的行存储在临时缓冲区中,接着使用sed命令处理缓冲区中的内容,处理完成后把缓冲区的内容送往屏幕,接着处理下一行,不断重复,直到文件末尾,文件内容没有改变,除非使用重定向存储输出
sed 【选项参数】‘command‘ filename
选项参数
-e 直接在指令模式上进行sed的动作编辑
命令
a 新增,a的后面添加字符串,在下一行出现
d 删除
s查找并替换
在第二行添加
[root@yangdong shelltest]# cat cut.txt dong shen guan zhen wo wo lai lai le le [root@yangdong shelltest]# sed "2a mei nv" cut.txt dong shen guan zhen mei nv wo wo lai lai le le
删除wo
[root@yangdong shelltest]# cat cut.txt dong shen guan zhen wo wo lai lai le le [root@yangdong shelltest]# sed "/wo/d" cut.txt dong shen guan zhen lai lai le le
把wo替换为ni g表示全局替换
[root@yangdong shelltest]# cat cut.txt dong shen guan zhen wo wo lai lai le le [root@yangdong shelltest]# sed "s/wo/ni/g" cut.txt dong shen guan zhen ni ni lai lai le le
删除第二行并且把wo替换为ni
[root@yangdong shelltest]# cat cut.txt dong shen guan zhen wo wo lai lai le le [root@yangdong shelltest]# sed -e "2d" -e "s/wo/ni/g" cut.txt dong shen ni ni lai lai le le
awk文本分析工具,把文件逐行的读入,以空格为默认的分隔符将每行切片,切开的部分再进行分析处理
awk【选项参数】 ‘pattern{action} pattern2{action2}。。。’ filename
pattern 表示awk在数据中查找的内容,就是匹配模式
action 在找到匹配内容时所执行的一系列命令
选项参数
-F 指定输入文件,拆分隔符
-v 赋值一个用户定义变量
awk内置变量
FILENAME 文件名
NR 已读记录数
NF 切割后列的个数
在passwd文件中 以:为分隔符,以root为开头匹配,以“,”分割,打印第一列和第七咧
[root@yangdong shelltest]# cat passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin [root@yangdong shelltest]# awk -F : '/^root/ {print $1","$7}' passwd root,/bin/bash
在passwd文件中,以:为分割,在第一行添加user,shell,打印第一列和第七列,在最后一行添加 dahaige,/bin/zuishuai
begin在所有数据读取行之前执行,end是在所有数据执行之后执行
[root@yangdong shelltest]# cat passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync [root@yangdong shelltest]# awk -F : 'BEGIN{print "user,shell"} {print $1","$7} END{print "dahaige,/bin/zuishai"}' passwd user,shell root,/bin/bash bin,/sbin/nologin daemon,/sbin/nologin adm,/sbin/nologin lp,/sbin/nologin sync,/bin/sync dahaige,/bin/zuishai
在passwd文件中,以:为分割,定义变量i=1,打印第三列,并且数值加1
[root@yangdong shelltest]# cat passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin [root@yangdong shelltest]# awk -F : -v i=1 '{print $3+i}' passwd 1 2 3 4
在passwd文件中,以:为分割,打印passwd文件名,每行的行号,每行的列数
[root@yangdong shelltest]# awk -F : '{print FILENAME "," NR "," NF}' passwd passwd,1,7 passwd,2,7 passwd,3,7 passwd,4,7 passwd,5,7 passwd,6,7
sort将文件进行排序,并将排序结果标准输出
sort(选项)(参数)
选项
-n 依照数值大小排序
-r 以相反的顺序来排序
-t 设置排序时所用的分割字符
-k 指定需要排序的列
参数:指定待排序的文件列表
对sort.sh文件以:为分隔符,指定第二列,以数值大小反序排列
[root@yangdong shelltest]# cat sort.sh bb:40:5.4 bd:20:4.2 xz:50:2.3 cls:10:3.5 ss:30:1.6 [root@yangdong shelltest]# sort -t : -nrk 2 sort.sh xz:50:2.3 bb:40:5.4 ss:30:1.6 bd:20:4.2 cls:10:3.5 [root@yangdong shelltest]# sort -t : -nrk 3 sort.sh bb:40:5.4 bd:20:4.2 cls:10:3.5 xz:50:2.3 ss:30:1.6