不知道大家平时有没有跟我一样的感受,就是很多shell命令自己其实用过,但时间一久又忘记了,导致又要到处百度。开始写这个系列的目的第一是为了总结,第二是为了以后忘记时可以直接到这找。平时在百度时还发现一个问题,就是其实我只想要最常用的命令,但是你给我列出一堆,并不实用,作为选择困难症的我,我会选择记最简单。本次总结都会列出工作中最常用的一些命令。
本篇篇幅可能会有点长,但是能覆盖大部分场景,以后看这一篇就够了
vim
三种模式
命令模式:可以输入快捷键进行一些操作(如删除行,复制行,移动光标,粘贴等等)
编辑模式:在该模式下可以对文件的内容进行编辑
末行模式:可以在末行输入命令来对文件进行操作(搜索、替换、保存、退出等)
打开文件的方式
# 直接打开# vim 文件路径# 打开文件,光标指定到指定行数# vim +数字 文件的路径# 打开指定文件,关键字高亮# vim +/关键词 文件的路径# 打开多个文件# vim 文件1 文件2
光标移动
# 行首# shift + ^# 行尾# shift + $# 首行# gg# 末行# G# 翻屏# 向上翻屏# ctrl + b(before) 或 PgUp# 向下翻屏# ctrl + f(after) 或 PgDn# 快速将光标移动到指定的行# 数字+G# 末行模式:: + 数字# 以光标为基准移动n# 数字+ ↑ 向上移动n行# 数字 + ↓ 向下移动n行# 数字 + ← 向左移动n个字符# 数字 + → 向后移动n个字符
末行模式
# 另存输入: ":w 文件路径"# 调用外部命令输入: ":!外部命令"# 搜索/查找# 输入: "/关键词"# 搜索结果中切换上/下一个: N/n# 取消高亮# 输入: ":nohl" 【nohighlight】# 替换# ":s/搜索的关键词/新的内容" 替换光标所在行的第一个符合条件的内容# ":s/搜索的关键词/新的内容/g" 替换光标坐在行的所有符合条件的内容# ":%s/搜索的关键词/新的内容" 替换整个文档中每行第一个符合条件的内容# ":%s/搜索的关键词/新的内容/g" 替换整个文档符合条件的内容% 表示整个文件g 表示全局(global)# 显示行号# ":set nu" number# 不显示行号# ":set nonu"# 使用vim同时打开多个文件,在末行模式下进行切换文件# 查看当前已经打开的文件名称: ":files"%a 表示当前正在打开的文件(active)# 表示上一个打开的文件# 切换文件# ":open 文件名"# ":bn" 切换到下一个文件# ":bp" 切换到上一个文件
编辑模式
# 控制显色# ":syntax on"# 计算器的使用# 进入编辑模式# 按下 "ctrl + r",然后输入=,光标变到最后一行# 输入需要计算的内容,按下回车
vim的配置
1. 在文件打开的时候末行模式下输入的配置(临时的)2. 个人配置文件(~/.vimrc,如果没有可自行配置)3. 全局配置文件(vim自带,/etc/vimrc)需要的配置直接往里添加,如set nu,syntax on等等针对同一个配置项,个人配置文件中存在,则以个人配置文件为准。如果个人配置文件中不存在这一项,则以全局配置文件为准。
运行模式
在Linux中存在一个进程:init(initialize,初始化),进程id是1
#查看该进程ps -ef | grep init
该进程存在一个对应的配置文件:inittab(系统运行级别配置文件,位置/etc/inittab)
0 - 表示关机级别(不要将默认的运行级别设置成这个值) 1 - 单用户模式 2 - 多用户模式,不带NFG(Network File System) 3 - 多用户模式,完全的多用户模式 4 - 没有被使用的模式(被保留模式) 5 - X11,完整的图形化界面模式 6 - 表示重启级别(不要将默认的运行级别设置成这个值)
# 切换到纯命令模式init 3# 回到桌面模式init 5# 设置模式永久为命令行模式# 将/etc/inittab文件中的initdefault值设置成3,然后重启操作系统
用户和用户组管理
三个重要的文件
# 存储用户的关键信息/etc/passwd# 存储用户组的关键信息/etc/group# 存储用户的密码信息/etc/shadow
用户管理
# 添加用户# 常用语法useradd 选项 用户名常用选项:-g:表示指定用户的用户主组,选项的值可以是用户组的id,也可以是组名-G: 表示指定用户的用户附加组,选项的值可以是用户组的id,也可以是组名-u: uid,用户的id(用户的标识符),系统默认会从500之后按顺序分配uid-c: comment,添加注释查看用户的主组可以查看passwd文件,查看附加组可以查看group文件。# 修改用户# 常用语法(modify)usermod 选项 用户名常用选项:-g:表示指定用户的用户主组,选项的值可以是用户组的id,也可以是组名-G: 表示指定用户的用户附加组,选项的值可以是用户组的id,也可以是组名-u: uid,用户的id(用户的标识符),系统默认会从500之后按顺序分配uid-l: 修改用户名。user -l 新用户名 老用户名# 设置密码# Linux不允许没设置密码的用户进入# 常用语法passwd 用户名# 删除用户# 常用语法userdel 选项 用户名# 常用选项-r: 表示删除用户的同时,删除其家目录
主组和附加组的区别
主组:如果没有指定用户组,创建用户的时候系统会默认同时创建一个和这个用户名同名的组,这个组就是基本组,不可以把用户从基本组中删除。在创建文件时,文件的所属组就是用户的基本组。
附加组:除了基本组之外,用户所在的其他组,都是附加组。用户是可以从附加组中被删除的。
用户不论在基本组还是附加组中,都会拥有该组的权限。一个用户可以属于多个附加组。但是一个用户只能拥有一个基本组。
用户组管理
用户组的管理涉及用户组的添加、删除和修改。组的增加、删除和修改实际上是对/etc/group文件的更新
# 添加用户组# 常用语法groupadd 选项 用户组名# 常用选项:-g: 类似用户添加里的"-u",-g表示设置一个自定义的用户组id,默认500后递增。# 编辑用户组# 常用语法groupmod 选项 用户组名# 常用选项-g: 类似用户添加里的"-u",-g表示设置一个自定义的用户组id,默认500后递增。-n: 类似用户修改里的"-l",设置新的用户组名# 用户组删除# 常用语法groupdel 用户组名注意:当如果需要删除一个组,但是这个组是某个用户的主组时,不允许删除,需要先从组内移出所有用户
主机名
临时设置主机名
# 临时设置主机名,需要切换用户使之生效hostname 主机名
永久设置主机名(需要重启)
# 找到配置文件vi etc/sysconfig/network# 修改其中的HOSTNAME为自己需要设置的永久主机名
如果想立即生效,再用hostname命令设置临时主机名
chkconfig
提供开启启动项的一个管理服务
在Linux下不是所有的软件安装完成之后都有开机启动服务,有的可能需要自己去添加,除此之外还可查看和删除。
# 开启启动服务查询chkconfig --list# 删除服务chkconfig --del 服务名# 例如删除httpd服务# 添加开机启动服务chkconfig --add 服务名# 注意:不是所有的服务都有服务名# 设置服务在某个级别下开机启动/不启动chkconfig --level 连在一起的启动级别 服务名 on/off# 如:设置服务在35级别下启动chkconfig --level 35
时间同步ntp
一次性同步时间
ntpdate 时间服务器的域名或ip地址
设置事件同步服务
# 启动ntpd服务service ntpd start 或 etc/init.d start
rpm管理
作用:对linux服务器上的软件包进行对应管理操作。分为:查询、卸载、安装
# 查询某个软件的安装情况rpm -qa | grep 关键词选项:-q: 查询,query-a: 全部,all# 卸载rpm -e 软件包名# 当存在依赖关系的时候又不想去解决这个问题的时候可以:rpm -e 软件包名 --nodeps# 软件安装rpm -ivh 软件包完整名称# 选项:-i: install-v: 显示进度条-h: 表示以"#"显示进度条
crontab计划任务
可以在指定的时间点去执行任务
# 语法crontab 选项# 常用选项-l: list,列出指定用户的计划任务列表-e: edit,编辑指定用户的计划任务列表-u: user,指定用户名,如果不指定,则表示当前用户-r: remove,删除指定用户的计划任务列表# 编辑crontab -e# 一行为一个计划任务#分 时 日 月 周 需要执行的命令* * * * * ll >> test.txt
权限
# 超级管理员可以设置某些用户不允许设置计划任务vi etc/cron.deny# 里面写用户名,一行一个# 白名单。本身不存在,需要自己创建。白名单优先级高于黑名单vi etc/cron.allow
grep 工具
grep是行过滤工具;用于根据关键字进行行过滤
语法和选项
# grep [选项] '关键字' 文件名
常见选项
-i: 不区分大小写-v: 查找不包含指定内容的行,反向选择-w: 按单词搜索-o: 打印匹配关键字-c: 统计匹配到的次数-n: 显示行号-r: 逐层遍历目录查找-A: 显示匹配行及后面多少行-B: 显示匹配行及前多少行-c: 显示匹配行前后多少行^key: 以关键字开头key$: 以关键字结尾^$: 匹配空行--color=auto: 显示颜色
cut
cut是列截取工具,用于列的截取
语法
# cut 选项 文件名
常见选项
-c: 以字符为单位进行分割,截取-d: 自定义分隔符,默认为指标符\t-f: 与-d一起使用,指定截取哪个区域
举例说明
# 以冒号分割,截取第1列内容cut -d: -f 1 1.txt# 以冒号分割,截取第1,6,7列内容cut -d: -f1,6,7 1.txt# 截取文件中每行第4个字符cut -d: -c4 1.txt# 截取文件中每行的第1-4个字符cut -d: -c1-4 1.txt# 截取文件中每行第5个字符开始后面的所有字符cut -d: -c5- 1.txt
小练习
列出当前系统的运行级别
runlevel | cut -c3runlevel | cut -d ' ' -f2grep -v '^#' etc/inittab | cut -d: -f2
sort工具
sort工具用于排序;它将文件的每一行作为一个单位,从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出
语法和选项
-u: 去除重复行-r: 降序排列,默认是升序-o: 将排序结果输出到文件中,类似于重定向符>-n: 以数字排序,默认是按字符排序-t: 分隔符-k: 第N列
举例说明
# 按照用户的uid进行升序排列sort -n -t: -k3 1.txt# 按照用户的uid进行降序排列sort -nr -t: -k3 1.txt# 按照数字排序并且去重sort -nu 1.txt# 按照数字排序并将结果重定向到文件sort -n -t: -k1 1.txt -o 2.txt
命令行常见快捷键
# ^ 代表control# 终止前台运行的程序^c# 将前台运行的程序挂起到后台^z# 退出 等价exit^d# 清屏^l# 光标移动到命令行的最前端^a | home# 光标移动到命令行的最后端^e | end# 删除光标前所有字符^u# 删除光标后所有字符^k# 搜索历史命令^r
bash中的引号
•双引号"":会把引号的内容当成整体来看待,允许通过$()符号引用其他变量值•单引号': 会把引号的内容当成整体来看待,禁止引用其他变量,shell中特殊字符都被视为普通字符。•反撇号``: 反撇号和$()一样,引号或括号里的命令会优先执行,如果存在嵌套,反撇号不能用。
wudeMacBook-Pro:~ kris$ echo $(date +%F)2021-04-09wudeMacBook-Pro:~ kris$ echo "$(date +%F)"2021-04-09wudeMacBook-Pro:~ kris$ echo '$(date +%F)'$(date +%F)wudeMacBook-Pro:~ kris$ echo $(echo `date +%F`)2021-04-09
系统变量
shell本身已经固定好了它的名字和作用
# 上一条命令执行后返回的状态;状态值为0表示正常,非0表示异常$?# 当前执行的程序或脚本名$0# 脚本后面接的参数的个数$## 脚本后面所有参数,当成一个整体输出,用空格隔开$*# 脚本后面所有参数,参数是独立的,也是全部输出$@# 脚本后面的位置参数,$1表示第一个位置参数$1-$9# 扩展位置参数,第10个位置变量必须用{}括起来(2位数字以上)${10}~${n}# 当前所在进程号$$# 调用最后一条命令历史中的参数!$
$*和$@的区别
#!/bin/bashfor i in "$@"doecho $idoneecho "======我是分割线======="for i in "$*"doecho $idonewudeMacBook-Pro: bash 3.sh a b cabc======我是分割线=======a b c
简单四则运算
默认情况下,shell就只能支持简单的整数运算
运算内容:加(+)、减(-)、乘(*)、除(/)、取余(%)
四则运算符
# $(())echo $((1+1))# $[]echo $[10-5]# expr 注意数字和运算符之间要有空格expr 10 5# let 变量运算n=1;let n+=1
变量的定义
基本方式
直接赋值给一个变量
A=123456echo $A# 表示从A变量第三个字符开始截取,截取4个字符echo ${A:2:4}# $变量名和${变量名}的区别。# ${}可以只截取一部分
命令执行结果赋值给变量
B=`date +%F`echo $B# 输出内核版本C=$(uname -r)echo $C
交互式定义变量(read)
语法:read [选项] 变量名
常见选项:
-p: 定义提示用户的信息-n: 定义字符数(限制变量值的长度)-s: 不显示(不显示用户输入的内容)-t: 定义超时时间,默认单位为秒(限制用户输入变量值的超时时间)
举例说明
# 用户自己定义变量值read -p "Please Input your name:" nameecho $name# 变量值来自文件cat 1.txt1.1.1.1 2.2.2.2read ip mask < 1.txtecho $ip1.1.1.1echo $mask2.2.2.2
定义有类型的变量(declare)
目的:给变量做一些限制,固定变量的类型,比如:整型,只读
用法:declare 选项 变量名=变量值
常用选项:
# -i: 将变量看成整数declare -i A=123# -r: 定义只读变量declare -r B=hello# -x: 将变量通过环境导出,等同于exportdeclare -x AAA=123456
关联数组定义
数组赋值
# 一次赋一个值array1[linux]=onearray1[java]=twoarray1[php]=three# 一次赋多个值array2=([name1]=harry [name2]=jack [name3]=amy [name4]="Miss Hou")array=(1 2 3)# 动态赋值array=($(ls home))
获取关联数组值
# 获取某个值# echo ${asso_array1[linux]}one# echo ${asso_array1[php]}three# 获取所有值# echo ${asso_array1[*]}three two one# 获取所有key# echo ${!asso_array1[*]}php java linux# 获取数组长度# echo ${#asso_array1[*]}3# echo ${#asso_array2[*]}4
条件判断语法格式
•格式1 test条件表达式•格式2 [ 条件表达式 ]•格式3 [[ 条件表达式 ]] 支持正则
特别说明:[]和[[]]两边都有空格!!!
判断文件类型
•-e:判断文件是否存在(link文件指向的也必须存在),exists•-f:判断文件是否存在并且是一个普通文件,file•-d:判断文件是否存在并且是一个目录,directory•-L:判断文件是否存在并且是一个软链接,soft link•-s:判断文件是否存在并且是一个非空文件(有内容),is not empty
test -e file 只要文件存在条件为真[ -d test/1 ] 判断目录是否存在,存在条件为真[[ ! -d test/1 ]] 判断目录是否存在,不存在条件为真[[ -f test/1.txt ]] 判断文件是否存在,并且是一个普通文件
判断文件权限
•-r:当前用户对其是否可读•-w:当前用户对其是否可写•-x:当前用户对其是否可执行•-u:是否有suid,冒险位。指文件操作者(用户)临时拥有文件拥有者的权限•-g:是否有sgid,强制位。一般针对的是目录。如果一个目录拥有强制位,那么任何用户在该目录里所创建的任何文件的属组都会继承该目录的属组•-k:是否有t位,粘滞位,一般针对的是公共目录,如果一个公共目录拥有粘滞位,那么该目录下的文件,只有root和文件的创建者可以删除,其他人只能自己管理自己
判断文件新旧
说明:这里的新旧指的是文件的修改时间
file1 -nt file2 比较file1是否比file2新file1 -ot file2 比较file2是否比file2旧file1 -ef file2 比较是否为同一个文件,或者用户判断硬链接,是否指向同一个inode
判断整数
•-eq ==: 相等,test 1 == 2,test 1 -eq 2•-ne <> !=: 不等•-gt: 大于•-lt: 小于•-ge: 大于等于•-le: 小于等于
判断字符串
•-z:是否为空字符串,字符串长度为0则成立•-n:判断是否为非空字符串,字符串长度不为0则成立•string1 = string2:判断字符串是否相等•string1 != string2:判断字符串是否不等
多重条件判断
•-a和&&:逻辑与,[ 1 -eq 1 -a 1 -ne 0 ],[ 1 -eq 1 ]&&[ 1 -ne 0 ]•-o和||:逻辑或,[ 1 -eq 1 -o 1 -ne 1 ]
特别说明:
•&&前面的表达式为真,才会执行后面的代码•||前面的表达式为假,才会执行后面的代码
举例说明
•数值比较
wudeMacBook-Pro:~ kris$ [ $(id -u) -eq 501 ] && echo "It is Kris"It is KriswudeMacBook-Pro:~ kris$ [ $(id -u) -ne 501 ] && echo "It is not Kris"wudeMacBook-Pro:~ kris$ [ $(id -u) -eq 50 ] && echo "It is Kris" || echo "It is not Kris"It is not Kris
•类C风格的数值比较
注意:在(())中,=表示赋值,==表示判断
wudeMacBook-Pro:~ kris$ ((1==1));echo $?0wudeMacBook-Pro:~ kris$ ((2>=1));echo $?0wudeMacBook-Pro:~ kris$ ((2!=1));echo $?0wudeMacBook-Pro:~ kris$ ((a=1));echo $a1wudeMacBook-Pro:~ kris$ ((a==123));echo $a1
•字符串比较
注意:双引号引起来,看做一个整体;=和==在[字符串]比较中都表示判断
wudeMacBook-Pro:~ kris$ a="Hello";b="World"wudeMacBook-Pro:~ kris$ [ $a == $b ];echo $?1wudeMacBook-Pro:~ kris$ [ $a = $b ];echo $?1wudeMacBook-Pro:~ kris$ [ "$a" = "$b" ];echo $?1wudeMacBook-Pro:~ kris$ [ "$a" != "$b" ];echo $?0wudeMacBook-Pro:~ kris$ test "$a" != "$b";echo $?0wudeMacBook-Pro:~ kris$ a=wudeMacBook-Pro:~ kris$ test -z $a;echo $?0wudeMacBook-Pro:~ kris$ test -z "$a";echo $?0wudeMacBook-Pro:~ kris$ test -n "$a";echo $?1wudeMacBook-Pro:~ kris$ [ -z $a ];echo $?0wudeMacBook-Pro:~ kris$ [ -n $a ];echo $?0wudeMacBook-Pro:~ kris$ [[ -n $a ]];echo $?1wudeMacBook-Pro:~ kris$ [ 1 -eq 0 -a 1 -ne 0 ];echo $?1wudeMacBook-Pro:~ kris$ [ 1 -eq 1 -a 1 -ne 0 ];echo $?0wudeMacBook-Pro:~ kris$ [ 1 -eq 1 && 1 -ne 0 ];echo $?-bash: [: missing `]'2wudeMacBook-Pro:~ kris$ [[ 1 -eq 1 && 1 -ne 0 ]];echo $?0
注意[]和[[]]的区别:
1.当变量为空时,使用单个[]会出现判断错误,要加上双引号,而两个[[]]可以不用加,所以推荐以后直接使用[[]]。2.在[[]]中可以使用&&,||,而单个不行3.[[]]支持c风格
逻辑运算符总结
•test exp1•[ exp1 ]•[[ exp1 ]]•((类c风格整数表达式exp1))•-s判断文件不为空•符号;和&&和||都可以用来分割命令或者表达式•分号(;)完全不考虑前面的语句是否正确执行都会执行后面的;•&&符号,需要考虑&&前面的语句的正确性,前面语句正确执行才会执行&&后的内容;反之亦然•||符号,需要考虑||前面的语句非正确性,前面语句执行错误才会执行||后内容;反之亦然•如果&&和||一起出现,从左往右依次看,按照以上原则
流程控制语句
注意if开头和fi结尾,注意if之后要加then
if [ condition1 ];thencommand1if [ condition2 ]thencommand2fielseif [ condition3 ];thencommand3elif [ condition4 ];thencommand4elsecommand5fifi
整体结构为:if...elif...else...fi
案例
判断两台主机是否ping通
思路:
•使用ping -c指定只ping一次•根据命令执行结果来判断是否成功•根据逻辑和语法结构来编写脚本(条件判断或流程控制)
#!/bin/bash# Author:.....read -p "请输入您要检查的主机" ip &>/dev/nullping -c 1 $ipif [ $? -eq 0 ];thenecho "该主机$ip正常连通"elseecho "该主机$ip无法连通"fi
判断一个进程是否存在
#!/bin/bash#判断httpd的进程是否存在pgrep httpd &>/dev/nullif [ $? -eq 0 ];thenecho "running"elseecho "not running"fi或者test $? -eq 0 && echo "running" || echo "not running"
补充命令
pgrep命令:以名称为依据从运行进程队列中查找进程,并显示查找到的进程id
•-o: 仅显示找到的最小(起始)进程号•-n: 仅显示找到的最大(结束)进程号•-l: 显示进程名称•-p: 指定父进程号;pgrep -p 4764 查询父进程下的子进程id•-g: 指定进程组•-t: 指定开启进程的终端•-u: 指定进程的有效用户ID
判断用户是否存在
#!/bin/bashread -p "请输入用户名: " usernameid $username &>/dev/nullif [ $? == 0 ];thenecho "存在"elseecho "不存在"fi
for循环
列表循环
•基本语法格式
for variable in {list}docommandcommanddone或者for variable in a b cdocommandcommanddone
•举例说明
for var in {1..10}; do echo $var; donefor var in 1 2 3 4 5 6;do echo $var; donefor var in $(seq 10);do echo $var;donefor var in `seq 10 -2 1`;do echo $var;done
不带列表循环
不带列表的for循环执行时由用户指定参数和参数的个数决定
for variabledocommanddone举例:#!/bin/bashfor vardoecho $vardoneecho "脚本后面有$#个参数"
类C风格的for循环
•基本语法结构
for (( expr1;expr2;expr3))docommandcommanddone举例:for (( i=1;i<=5;i++))doecho $idone或for ((i=1;i<=5;i++));do echo $i;done
应用案例
脚本计算1-100奇数和
#!/bin/bashsum=0for i in {1..100}doif test $[$i%2] -ne 0thenlet sum+=$ifidoneecho "result: $sum"
循环控制语句
•continue:继续,执行下一次循环•break: 打断;马上停止该循环体•exit:表示直接退出程序
#!/bin/bashfor i in {1..5}do[ $i -eq 2 ] && break || echo $idone
案例
批量创建用户
要求家目录都在/rhome,不存class组则创建
#!/bin/bash[ -f rhome ] && mv rhome rhome.bak[ ! -d rhome ] && mkdir rhome# 判断class组是否存在grep -w ^class etc/group &>/dev/null# 不存在则创建class组[ $? -ne 0 ] && groupadd class# 循环创建用户for ((i=1;i<=5;i++))do# 创建用户,指定附加组Guseradd -d rhome/user$i -G class user$i# 设置密码echo "123" | passwd --stdin user$idone
局域网内脚本检查主机网络通讯
局域网内,把能ping通的ip和不能ping通的ip分类,并保存到两个文本文件里 以10.1.1.1~10.1.1.10为例
#!/bin/baship=10.1.1# 循环ping主机的ipfor ((i=1;i<=10;i++))doping -c 1 $ip.$i &>/dev/nullif [ $? -eq 0 ]thenecho $ip.$i >> ip_up.txtelseecho $ip.$i >> ip_down.txtfidone
延伸扩展:shell脚本并发
并行执行:
{程序}& 表示将程序放到后台并行执行,如果需要等待程序执行完毕再进行下面内容,需要加wait
#!/bin/baship=10.1.1# 循环ping主机的ipfor ((i=1;i<=10;i++))do{ping $ip.$i -c 1 & > dev/nullif [ $? -eq 0 ]thenecho $ip.$i >> ip_up.txtelseecho $ip.$i >> ip_down.txtfi}&done# 等待程序执行完成waitecho "ip check completed!"
总结
•for循环语法结构•for循环可以结合条件判断和流程控制语句•控制循环语句,continue,break,exit
while循环语句
条件为真就进入循环;为假就退出循环
while循环语法结构
while 表达式docommand...donewhile [ 1 -eq 1 ] 或者 (( 1 > 2 ))docommandcommand...done
应用案例
•脚本计算1-50偶数和
#!/bin/bashsum=0i=2while [ $i -le 50 ]dolet sum=sum+ilet i+=2doneecho "result=$sum"
•脚本同步系统时间,每30秒同步一次,失败发邮件告警,100次成功也发邮件
#!/bin/bashntp_server=10.1.1.1count=0while truedordate -s $ntp_server &>/dev/nullif [ $? -ne 0 ];thenecho "sync date failed" | mail -s "check system date" root@localhostelselet count++if [ count -eq 100 ];thencount=0echo "sync date success 100 times" | mail -s "check system date" root@localhostfifisleep 30done
until循环
特点:条件为假就进入循环;条件为真就退出循环
until语法结构
until expression [ 1 -eq 1 ] (( 1 >= 1))docommandcommand...done例如:打印1-5数字i=1while [ i -le 5 ]doecho $ilet i++done
应用案例
使用until语句批量创建10个用户,要求stu1-stu5用户的UID分别为1001-1005; stu6~stu10用户的家目录分别在/rhome/stu6-/rhome/stu10
#!/bin/bashstu_num=1until [ $stu_num -gt 10 ]doif [ $stu_num -le 5 ];thenuseradd -u $[1000+$stu_num] stu$stu_num && echo 123 | passwd --stdin stu$stu_numelse[ ! -d rhome ] && mkdir rhomeuseradd -d rhome/stu$stu_num stu$stu_num && echo 123 | passwd --stdin stu$stu_numfilet i++done
随机数
系统变量:RANDOM,默认会产生0~32767的随机整数
# 打印一个随机整数echo $RANDOM# 查看系统上一次生成的随机数set | grep RANDOM# 产生0~1之间的随机数echo $[$RANDOM%2]# 产生0~3之间的随机数echo $[$RANDOM%4]# 产生50-100之间的随机数echo $[$RANDOM%51+50]# 产生三位数的随机数echo $[$RANDOM%900+100]
影响shell程序的内置命令
•exit 退出整个程序•break 结束当前循环,或跳出本层存在•continue 忽略本次循环剩余代码,进入下一次循环•shift 使位置参数向左移动,默认移动1位,可以使用shift 2移动两位
举例说明
以下脚本都能够实现用户自定义输入数字,然后脚本计算和
shift实现
#!/bin/bashsum=0while [ $# -ne 0 ]dolet sum=sum+$1shiftdoneecho sum=$sum
for实现
#!/bin/bashsum=0for idolet sum=sum+$idoneecho sum=$sum
expect
expect自动应答tcl语言
工作流程
except的工作流程可以理解为:spawn启动进程 --> expect期待关键字 --> send向进程发送字符 --> 退出结束
案例1
远程登录到server上什么都不做
#!/usr/bin/expect# spwan命令是expect的初始命令,它启动一个进程,之后所有expect操作都在这个进程中进行spawn ssh root@192.168.123.20# 捕获相关内容expect {# exp_continue表示如果没有则往下匹配"(yes/no)?" { send "yes\r";exp_continue }"password:" { send "123456\r" }}# interact 执行完成后保持交互状态,把控制权交给控制台interact
执行方式:
./test_expect.shexpect -f test_expect.sh
获取位置参数定义变量
#!/usr/bin/expectset ip [ lindex $argv 0 ]set pass [ lindex $argv 1 ]set timeout 5spawn ssh root@192.168.123.20expect {"password:" { send "123456\r" }}interact
案例2
远程到server上操作
#!/usr/bin/expectset ip [ lindex $argv 0 ]set passwd [ lindex $argv 1 ]spawn ssh root@192.168.123.20expect {"password:" { send "$passwd\r" }}expect "#"send "touch tmp/file{1..3}\r"send "date\r"send "exit\r"expect eof
expect eof 表示交互结束,退回到原用户
案例3
shell脚本和expect结合使用
#!/bin/bashcat ip.txt | while read ip passdo# 指定expect的结束标识符usr/bin/expect <<-END &>/dev/nullspawn ssh root@$ipexpect {"yes/no" { send "yes\r";exp_continue }"password" { send "$pass\r" }}expect "#"send "touch tmp/file{1..4}\r"send "exit\r"expect eofENDdone或#!/bin/bash# 循环在指定的服务器上创建用户和文件while read ip passdousr/bin/expect <<-END &>/dev/nullspawn ssh root@$ipexpect {"yes/no" { send "yes\r";exp_continue }"password:" { send "$pass\r" }}expect "#" { send "useradd yy1;rm -rf tmp/*;exit\r" }expect eofENDdone < ip.txt
在远程机器执行完成后最好执行exit来退出远程机器,不然可能会导致执行缓慢
case语句
一、case语句
语法结构
case var inpattern1)command;;patteern2)command;;*) default,不满足以上模式,默认执行*)下面的语句command;;;esac
二、应用案例
给程序传入不同的值时做不同的事
#!/bin/bashcase $1 instart|S)service apache start &>/dev/null && echo "apache 启动成功";;stop|T)service apache stop &>/dev/null && echo "apache 停止成功";;restart|R)service apache restart &>/dev/null && echo "apache 重启成功";;*)echo "请输入要做的事情...";;esac
函数function
一、 什么是函数
•shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数•给这段代码起个名字称为函数名,后续可以直接调用这段代码的功能
二、 如何定义函数
方法1:
函数名(){函数体(一堆命令的集合,来实现某个功能)}
方法2:
function 函数名(){command...}
函数中return说明:
1.return可以结束一个函数.2.return默认返回函数中最后一个命令状态值,也可以给定参数值,范围是0~2563.如果没有return命令,函数将返回最后一个指令的退出状态值
三、 函数如何调用
# 当前命令行调用wudeMacBook-Pro:shelltest kris$ source test_function.shwudeMacBook-Pro:shelltest kris$ helloHello World!wudeMacBook-Pro:shelltest kris$ cat test_function.sh#!/bin/bashfunction hello(){echo "Hello World!"}# 脚本中调用wudeMacBook-Pro:shelltest kris$ bash test_function2.sh1.start2.stop3.restart4.helpSuccess!wudeMacBook-Pro:shelltest kris$ cat test_function.sh#!/bin/bashfunction hello(){cat <<-EOF1.start2.stop3.restart4.helpEOF}wudeMacBook-Pro:shelltest kris$ cat test_function2.sh#!/bin/bashsource test_function.shhello && echo "Success!"
四、应用案例
要求:用户如果不输入就循环让用户输入,并且打印输入结果
wudeMacBook-Pro:shelltest kris$ cat test_function3.sh#!/bin/bashinput_fun(){input_value=""while [ -z $input_value ]doread -p $1 input_valuedoneecho "Input Value is $input_value"}input_fun "请输入你的姓名:"
屏蔽信号
当我们希望脚本在运行时不受其他信息干扰时(如ctrl+c),可以在脚本中使用信号屏蔽
# 屏蔽以下信号trap '' 1 2 3 19
1) SIGHUP 重新加载配置
2) SIGINT 键盘中断^C 3) SIGQUIT 键盘退出 9) SIGKILL 强制终止 15) SIGTERM 终止(正常结束),缺省信号 18) SIGCONT 继续 19) SIGSTOP 停止 20) SIGTSTP 暂停^Z
正则表达式
正则表达式是什么
正则表达式(Regular Expression 、regex或regexp缩写为RE),也译为正规表达式法、常规表达式法,是一种字符模式,用于在查找过程中匹配指定的字符。
许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。
正则表达式这个概念最初由Unix中的工具软件(例如sed和grep)普及开的。
支持正则表达式的程序如:locate | find | vim | grep | sed | awk
正则能干什么
1.匹配邮箱、匹配身份证号码、手机号、银行卡号等2.匹配某些特定字符串,做特定处理等
正则当中名词解释
•元字符
指那些在正则表达式中具有特殊意义的专用字符,如(. * ?)等
•前导字符
位于元字符前面的字符 .abc* aooo.
(一)正则中普通常用的元字符
| 元字符 | 功能 | 备注 |
| . | 匹配除了换行符以外的任意单个字符 | |
| * | 前导字符出现0次或连续多次 | |
| .* | 任意长度字符 | ab.* |
| ^ | 行首(以...开头) | ^root |
| $ | 行尾(以...结尾) | bash$ |
| ^$ | 空行 | |
| [] | 匹配括号里任意单个字符或一组单个字符 | [abc] |
| [^] | 匹配不包含括号里任一单个字符或一组单个字符 | [^abc] |
| ^[] | 匹配以括号里任意单个字符或一组单个字符开头 | ^[2] |
| ^[^] | 匹配不以括号里任意单个字符或一组单个字符开头 | ^[^abc] |
| < | 取单词的头 | |
| > | 取单词的尾 | |
| <> | 精确匹配 | |
| {n} | 匹配前导字符连续出现n次 | |
| {n,} | 匹配前导字符至少出现n次 | |
| {n,m} | 匹配前导字符出现n次与m次之间 | |
| () | 保存被匹配的字符 | |
| \d | 匹配数字(grep -P) | [0-9] |
| \w | 匹配字符数字下划线(grep -P) | [a-zA-Z0-9] |
| \s | 匹配空格、制表符、换页符(grep -P) | [\t\r\n] |
举例说明
# 将10.1.1.1替换成10.1.1.2541)vim编辑器支持正则表达式# vim 1.txt:%s#\(10.1.1\).1#\1.254#g:%s/\(10.1.1\).1/\1.254/g2)sed支持正则表达式【后面学】# sed -n 's#\(10.1.1\).1#\1.254#p' 1.txt10.1.1.254说明:找出含有10.1.1的行,同时保留10.1.1并标记为标签1,之后可以使用\1来引用它。最多可以定义9个标签,从左边开始编号,最左边的是第一个
扩展类正则常用元字符
•grep你要用我,必须加-E或者让你兄弟egrep来找我•sed你要用我,必须加-r
| 扩展元字符 | 功能 | 备注 |
| + | 匹配一个或多个前导字符 | bo+ 匹配boo、bo |
| ? | 匹配零个或一个前导字符 | bo? 匹配b、bo |
| \ | 或 | 匹配a或b |
| () | 组字符(看成整体) | (my|your)self:表示匹配myself或yourself |
| {n} | 前导字符重复n次 | |
| {n,} | 前导字符重复至少n次 | |
| {n,m} | 前导字符重复n到m次 |
# 过滤出文件中的ipgrep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" 1.txt
第二类正则
| 表达式 | 功能 | 示例 |
| [:alnum:] | 字母与数字字符 | [[:alnum:]]+ |
| [:alpha:] | 字符字符(包括大小写字母) | [[:alpha:]]{4} |
| [:blank:] | 空格与制表符 | [[:blank:]]* |
| [:digit:] | 数字 | [[:digit:]]? |
| [:lower:] | 小写字符 | [[:lower:]]{4,} |
| [:upper:] | 大写字母 | [[:upper:]]+ |
| [:punct:] | 标点符号 | [[:punct:]] |
| [:space:] | 包括换行符,回车等在内的所有空白 | [[:space:]]+ |
# 匹配数字开头的行grep -E "^[[:digit:]]+" 1.txt# 匹配不以数字开头的行grep -E "^[^[:digit:]]+" 1.txt# 匹配存在至少连续4个小写字母的行grep -E "[[:lower:]]" 1.txt
练习
1. 查找不以大写字母开头的行grep '^[^A-Z]' 1.txtgrep -v '^[A-Z]' 1.txtgrep '^[^[:upper:]]' 1.txt2. 查找有数字的行grep '[0-9]' 1.txtgrep -P '\d' 1.txt3. 查找一个数字和一个字母连起来的grep -E '[0-9][a-zA-Z]|[a-zA-Z][0-9]' 1.txt4. 查找不以r开头的行grep -v '^r' 1.txtgrep '^[^r]' 1.txt5. 查找以数字开头的grep '^[0-9]' 1.txt6. 查找以大写字母开头的grep '^[A-Z]' 1.txt7. 查找以点结束的grep '\.$' 1.txt8. 去掉空行grep -v '^$' 1.txt9.查找完全匹配abc的行grep '\<abc\>' 1.txt10.查找A后有三个数字的行grep -E 'A[0-9]{3}' 1.txtgrep 'A[0-9]\{3\}' 1.txt11.统计root在/etc/passwd里出现几次grep -o 'root' 1.txt | wc -l12. 找出文件中的ip地址grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 1.txt13. 找出全部数字的行grep -E '^[0-9]+$' 1.txtgrep --help:匹配模式选择:Regexp selection and interpretation:-E, --extended-regexp 扩展正则-G, --basic-regexp 基本正则-P, --perl-regexp 调用perl的正则-e, --regexp=PATTERN use PATTERN for matching-f, --file=FILE obtain PATTERN from FILE-i, --ignore-case 忽略大小写-w, --word-regexp 匹配整个单词
Sed
sed用来做啥
sed是Stream Editor(流编辑器)的缩写,简称流编辑器;用来处理文件的
sed如何处理文件
sed是一行一行读取文件内容并按照要求进行处理,把处理后的结果输出到屏幕
1.首先sed读取文件中的一行内容,把其保存在一个临时缓存区中(也称为模式空间)2.然后根据需求处理临时缓冲区的行,完成后把该行发送到屏幕上
使用方法
sed常见的语法格式有两种,一种叫命令行模式,另一种叫脚本模式。本次主要讲到命令格式,因为起始脚本模式就是命令的集中集合。
语法格式
sed [options] '处理动作' 文件名
•常用选项
| 选项 | 说明 | 备注 |
| -e | 进行多项(多次)编辑 | |
| -n | 取消默认输出 | 不自动打印模式空间 |
| -r | 使用扩展正则表达式 | |
| -i | 原地编辑(修改源文件) | |
| -f | 指定sed脚本的文件名 |
•常见处理动作
注意:以下的动作都要在单引号里
| 动作 | 说明 | 备注 |
| 'p' | 打印 | |
| 'i' | 在指定行前插入内容 | 类似vim里的大写O |
| 'a' | 在指定行之后插入内容 | 类似vim里的小写o |
| 'c' | 替换指定行所有内容 | |
| 'd' | 删除指定行 |
举例说明
文件准备
root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin298374837483172.16.0.25410.1.1.1
对文件进行增删改查操作
语法:sed 选项 '定位+命令' 文件
打印文件内容
sed '' a.txt 对文件什么都不做sed -n 'p' 打印每一行,并取消默认输出sed -n '1p' 打印第一行sed -n '1,5p' 打印1到5行sed -n '$p' 打印最后一行
增加文件内容
操作符:i 地址定位的上面插入,a地址定位的下面插入
sed '$a99999' a.txt 文件最后一行下面增加内容sed 'a9999' a.txt 在每行下面增加内容sed '5a99999' a.txt 在第5行下面增加内容sed '$i999999' a.txt 在最后一行上一行增加内容sed '/^root/i999' a.txt 以root开头行的上一行插入内容
修改文件内容
操作符:c 替换指定的整行内容
sed '5chello world' a.txt 替换第5行内容sed 'chello world' a.txt 替换文件所有内容sed '1,5chello world' a.txt 替换文件1到5行内容为hello worldsed '/^user01/c8888' a.txt 替换以user01开头的行
删除文件内容
sed '1d' a.txt 删除文件第1行 sed '1,5d' a.txt 删除文件1到5行 sed '$d' a.txt 删除文件最后一行
对文件进行搜索替换操作
语法: sed 选项 's/搜索的内容/替换的内容/动作' 处理的文件
其中,s表示搜索;斜杠**/表示分隔符,可以自己定义;动作一般是打印p和全局替换g
sed -n 's/root/ROOT/p' a.txt 将每行出现的第一个root替换为ROOT并打印sed -n 's/root/ROOT/gp' a.txt 全局替换root为ROOT并打印sed -n 's/^#//gp' a.txt 将以#开头的行打印并去除#sed -n 's@/sbin/nologin@xicent@gp' a.txt 将分隔符替换为@sed -n '1,5s/^/#/p' a.txt 注释1-5行
其他命令
| 命令 | 解释 | 备注 |
| r | 从另外文件中读取内容 | |
| w | 内容另存为 | |
| & | 保存查找串以便在替换串中引用 | 和()相同 |
| = | 打印行号 | |
| ! | 对所选行以外的所有行应用命令 | '1,5!' |
| q | 退出 |
r 从文件中读取输入行w 将所选的行写入文件sed '3r etc/hosts' a.txt 在a.txt的第三行增加文件内容sed '$r etc/hosts' a.txt 在a.txt的最后一行增加文件内容sed '/root/w root.txt' a.txt 将匹配的内容写入新的文件sed '/[0-9]{4}/p' a.txt 连续4个数字的行! 对所选行以外的所有行应用命令。放到行数之后sed -n '1!p' a.txt 打印除第一行以外的所有行sed -n '1,5!p' a.txt 打印除1至5行之外的行& 保存查找串以便在替换串中引用sed -n 's/root/#&/p' a.txt 将root替换为#rootsed -n -r 's/^root|^stu/#&/p' a.txt 注释以root开头或者以stu开头的行sed -n '1,5s/^[a-z].*/#&/p' a.txt 注释1~5行小写字母开头的行= 打印行号sed -n '/bash$/=' a.txt 打印以bash结尾的行的行号sed -n '/nologin$/=;/nogolin$/p' a.txt 打印以bash结尾的行的行号和内容q 退出sed '5q' 打印到第5行退出
其他选项
-e 多项编辑 -r 扩展正则 -i 修改原文件
sed -ne '/root/p' -ne '/root/=' a.txtsed -e '5ihello world' -e '8a哈哈哈哈' a.txt -e '5=;8=' 在a.txt文件的第5行的前面插入"hello world";在a.txt文件的第8行下面插入"哈哈哈"过滤vsftpd.conf文件中以#开头和空行grep -Ev '^#/^$' /etc/vsftpd/vsftpd.confsed -e '/^#/d' -e '/^$/d' /etc/vsftpd/vsftpd.confsed '/^#/d;/^$/d' /etc/vsftpd/vsftpd.confsed -r '/^#|^$/d' /etc/vsftpd/vsftpd.conf-i 选项 直接修改原文件sed -i 's/root/ROOT/;s/stu/STU' a.txtsed -i '1,5s/^/#&/' a.txt
sed结合正则使用
sed 选项 'sed命令或者正则表达式或者地址定位' 文件名
1.地址用于决定对哪些行进行编辑。地址的形式可以是数字、正则表达式、或二者的结合2.如果没有指定地址,sed将处理输入文件的所有行
| 正则 | 说明 | 备注 |
| /key/ | 查询包含关键字的行 | sed -n '/root/p' a.txt |
| /key1/,/key2/ | 匹配包含两个关键字之间的行 | sed -n '/admin/,/mysql/p' a.txt |
| /key/,x | 从匹配关键字的行开始到文件第x行之间的行(包含关键字所在行) | sed -n '^ftp/,7p' |
| x,/key/ | 从文件的第x行开始到与关键字的匹配行之间的行 | sed -n '7,/adm/p' a.txt |
| x,y! | 不包含x到y行 | |
| /key/! | 不包括关键字的行 | sed -n '/bash$/!p' a.txt |
awk
awk介绍
awk概述
awk是一种编程语言,主要用于linux、unix下对文件和数据进行处理,是Linux/unix下的一个工具。数据可以来自标准输入、一个或多个文件,或其他命令的输出。
awk的处理文本和数据的方式:逐行扫描文件,默认第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作
awk分别代表其作业姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。
gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展
下面介绍的awk是以GNU的gawk为例的,在Linux系统中已把awk连接到gawk,所以下面全部以awk进行介绍
awk能干啥
1.awk用来处理文件和数据的,是类unix下的一个工具,也是一个编程语言2.可以用来统计数据,比如网站的访问量,访问的IP量等等3.支持条件判断,支持for和while循环
使用方式
语法结构
awk 选项 '命令部分' 文件名
特别说明:引用shell变量需用双引号引起
常用选项介绍
•-F 定义字段分割符号,默认的分隔符是空格•-v 定义变量并赋值
使用方式
•正则表达式,地址定位
'/root/{awk语句}' sed中:'/root/p''NR==1,NR==5{awk语句}' sed中:'1,5p''/^root/,/^ftp/{awk语句}' sed中: '/^root/,/^ftp/p'
•{awk语句1;awk语句2}
'print $0;print $1' sed中:'p''NR==5{print $0}' sed中:'5p'
注:awk命令语句间用分号间隔
•BEGIN...END...
'BEGIN{awk语句};{处理中};END{awk语句}''BEGIN{awk语句};{处理中}''{处理中};END{awk语句}'
awk内部相关变量
| 变量 | 变量说明 | 备注 |
| $0 | 当前处理行的所有记录 | |
| $1,$2,$n | 文件中每行以间隔符分割的不同字段 | awk -F: '{print $1,$3}' |
| NF | 当前记录的字段数(列数) | awk -F: '{print NF}' |
| $NF | 最后一列 | $(NF-1)表示倒数第二列 |
| FNR/NR | 行号 | |
| FS | 定义间隔符 | 'BEGIN{FS=":"};{print $1,$3}' |
| OFS | 定义输出字段分隔符,默认空格 | 'BEGIN{OFS="\t"};{print $1,$3}' |
| RS | 输入记录分隔符,默认换行 | 'BEGIN{RS="\r"};{print $0}' |
| ORS | 输出记录分隔符,默认换行 | 'BEGIN{ORS="\n\n"};{print $1,$3}' |
| FILENAME | 当前输入的文件名 |
awk -F: '{print $1,$(NF-1),$NF,NF}' a.txtawk '/root/{print $0}' a.txtawk '/root/' a.txtawk 'NR==1,NR==5' a.txtawk 'NR==1,NR==5{print $0}' a.txtawk 'NR==1,NR==5;/^root/{print $0}' a.txt
awk工作原理
awk -F: '{print $1,$3}' /etc/passwd
1.awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符(RS)结束2.每行被间隔符:(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始。awk是如何知道用空格来分隔字段的呢?因为有一个内部变量FS来确定字段分隔符。初始时,FS赋为空格3.awk使用print函数打印字段,打印出来的字段会以空格分隔,因为$1,$3之间有一个逗号。逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格4.awk处理完一行后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕。
awk使用进阶
格式化输出print和printf
print函数 类似echo "hello world"date | awk '{print "Month: "$2"\nYear:"$NF}'printf函数 类似于echo -nawk -F: '{printf "%-15s %-10s %-15s\n",$1,$2,$3}' /etc/passwdawk 'BEGIN{FS=":"};{printf "%-15s %-15s %-15s\n",$1,$2,$NF}' a.txt
%s 字符类型 $d 数值类型 占15字符 -表示左对齐,默认右对齐 printf默认不会在行尾自动换行,加\n
awk变量定义
# awk中调用定义的变量不需要加$awk -v NUM=3 -F: '{ print NUM }' /etc/passwd
awk中BEGIN...END使用
1.BEGIN:表示在程序开始前执行2.END:表示所有文件处理完后执行3.用法:'BEGIN{开始处理之前};{处理中};END{处理结束后}'
# 输出最后一列和倒数第二列awk 'BEGIN{FS=":";print "Login_shell\tLogin_home\n******"};{print $NF"\t"$(NF-1)};END{print "***********"}' 1.txt
注意:中间处理函数的\t要用双引号引起来
awk和正则的综合应用
# 从第一行开始匹配到以lp开头行awk -F: 'NR==1,/^lp/{print $0}' passwd# 从第一行到第五行awk -F: 'NR==1,NR==5{print $0}' passwd# 从以lp开头的行匹配到第10行awk -F: '/^lp/,NR==10{print $0}' passwd# 从以root开头的行匹配到以lp开头的行awk -F: '/^root/,/^lo/{print $0}' passwd# 打印以root开头或者以lp开头的行awk -F: '/^root/ || /^lp/{print $0}' passwdawk -F: '/^root/;/^lp/{print $0}' passwd# 显示5-10行awk -F: 'NR>=5 && NR<=10{print $0}' /etc/passwd# 打印30-39以bash结尾的内容awk 'NR>=30 && NR<=39 && $0 ~ /bash$/{print $0}' passwdawk 'NR>=3 && NR<=8 && /bash$/' 1.txt
流程控制语句
if结构
格式:awk 选项 '正则,地址定位' 文件名 { if(表达式) {语句1;语句2;...} }
awk -F: '{if($3>=500 && $3<=60000){print $1,$3}}' passwdawk -F: '{if($==0){print $1"是管理员"}}'awk 'BEGIN{if('$(id -u)'==0){print "admin"}}'
if...else结构
{if(表达式){语句;语句;...}} else {语句;语句;...}}awk -F: '{if($3>=500 && $3!= 65534) {print $1"是普通用户"} else {print $1,"不是普通用户"}}'
if...else if...else结构
{ if(表达式1){语句;语句} else if(表达式2){语句;语句} else {语句}}awk -F: '{if($3==0){print $1":是管理员"} else if($3>=1 && $3<=499 || $3==65534){print $1,"是系统管理员"} else {print $1,"是普通用户"}}'
循环语句
for循环
打印1~5awk 'BEGIN{for(i=1;i<=5;i++){print i}}'打印1-5的和awk 'BEGIN{sum=0;for(i=1;i<=5;i++) sum+=i;print sum}'
while循环
打印1-5awk 'BEGIN{i=1;while(i<=5){print i;i++}}'打印1-5的和awk 'BEGIN{i=1;sum=0;while(i<=5){sum+=i;i++};print sum}'
awk算数运算
+ - * / %(模) ^(幂)可以在模式中执行运算,awk都将按浮点数方式执行算数运算awk 'BEGIN{print 1+1}'awk 'BEGIN{print 1**1}'awk 'BEGIN{print 2**3}'awk 'BEGIN{print 2/3}'
awk统计案例
统计系统中各种类型的shell
用到awk中的数组
# i是shells中的每个元素,shells[i]是这个元素的次数awk -F: '{shells[$NF]++};END{for(i in shells){print i,shells[i]}}' /etc/passwd
微信公众号:喜讯Xicent





