Shell编程四剑客及使用案例

Shell编程四剑客

Shell编程四剑客包括:find、sed、grep、awk

Find工具(系统中查找文件)

四剑客Find工具主要用于操作系统文件、目录的查找,其语法格式为:
find path -option [ -print ] [ -exec -ok command ]
{} \
常用option参数如下:
-name filename   #查找名为filename得文件
例:find /opt -name "*.txt" | xargs du -sh   查找/opt目录以.txt结尾的文件(xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令。)
   find /opt -name "[A-Z]*"  查找/opt目录以大写字母开头的文件
   find /opt -name "test*"   查找/opt目录以test开头的文件

-type b/d/c/p/l/f  #查是块设备、目录、字符设备、管道、符号链接、普通文件
例:find /opt/sh -type d
   find /opt/sh -type d | xargs du -h  查找/opt下目录并显示大小(-h以K,M,G为单位,提高信息的可读性;-s仅显示总计)
   du -h *     查看当前目录下各文件大小
   find /opt/sh -type d | xargs chmod 755 -R 查/opt/sh下目录并更改755权限
   
-size n[c]       #查长度为n块[或n字节]的文件
例:find /opt/sh -size +1M | xargs du -h  查/opt/sh目录下大于1M的文件并显示文件大小
   find /opt/sh -size 13M | xargs du -h  查/opt/sh目录下等于13M的文件并显示文件大小
   find /opt/sh -size -1M | xargs du -h  查/opt/sh目录下小于1M的文件并显示文件大小
   
--perm           #按执行权限来查找

--user   username   #按文件属主来查找

--group  groupname  #按组来查找

-mtime  -n +n       #按文件更改时间来查找文件,-n指n天以内,+n指n天以前
find /data/ -mtime +30 	-name 	"*.txt"  #查找30天以前的txt文件;
find /data/ -mtime 30 	-name  	"*.txt"	#查找第30天的log文件;
find /data/ -mtime -30 	-name 	"*.txt"  #查找30天以内的txt文件;
find /opt/ -mtime -30 -name "*.txt" | xargs  ls -l #查找30天以内的txt文件并显示时间

-atime  -n +n       #按文件访问时间来查找文件,-n指n天以内,+n指n天以前
-ctime  -n +n       #按文件创建时间来查找文件,-n指n天以内,+n指n天以前

-maxdepth           #查找目录级别深度
例:find /opt -maxdepth 1
find案例:
#查找/opt目录以.txt结尾,文件大于5K的文件,同时cp到/tmp/dd目录
find /opt -name "*.txt" -size +5k -exec cp {} /tmp/dd/ \;

#查找/opt/sh目录以.txt结尾,文件大于5K的文件,权限为644并删除该文件
find /opt/sh -name "*.sh" -size +2k -perm 644 -exec rm -rf {} \;

#查找/opt/sh目录以.sh结尾,30天以前的文件,大小大于1k并移动到/tmp/dd目录;
find /opt/sh -name "*.sh" -mtime +30 -size +1k -exec cp {} /tmp/dd \;

#搜索文件open*.rpm并将文件全部复制到/tmp/dd目录中
find / -name "open*.rpm" -exec cp {} /tmp/dd \;
find / -name “openwebmail*.rpm” |xargs –I {} cp {} /tmp/
exec表示单个结果逐个提交,找一个执行一个,比较稳定
xargs找到后统一传到大括号中,如果内容过大会导致内存不足,牺牲资源

which sed   主要找命令所在位置,不适合找配置文件
whereis sed  主要找命令所在位置,可找配置文件

sed工具(以行来编辑文件)

sed [-option] ['Commands'] filename
sed工具默认处理文本,文本内容输出屏幕已经修改,但是文件内容其实没有修改,需要加-i参数即对文件彻底修改。
s                	       		 #使用替换模式替换相应模式;
(-i) s/xxx/ddd/g                #s/g全文替换内容xxx内容替换为ddd(加入-i参数修改文件,不加则只显示不修改)
sed 's/old/new/g' q.txt       #全文替换old为new
sed '1,3s/old/new/g' q.txt    #1-3行替换old为new
sed '3s/old/new/g' q.txt      #替换第三行old为new
sed '/net/s/jfedu/kuo/g' q.txt   #找到net行并
sed '1s/root/kuo/g;3s/root/adamin/g' q.txt        #替换第一行和第三行的内容
sed -e '1s/old/new/g' –e '3s/old/new/g' jfedu.txt    #替换1和3行内容

x         #x为指定行号
sed -n '3p' q.txt

x,y       #指定从x到y的行号范围
sed    -n  '1,3p'           q.txt(-n静默显示,只显示匹配到得)
sed    -n '1p;$p'           q.txt     #打印第一行与最后一行

xp;yp                        #打印第x行和第y行
sed -n '1p;3p' q.txt

/pattern/                   #查询包含模式的行
sed -n '/1.17/p' q.txt

/pattern/,/pattern/           #查询包含两个模式及之间的行,/1.15/到/1.17/的行
sed -n '/1.15/,/1.17/p' q.txt    

/pattern/;/pattern/           #查询包含两个模式的行
sed -n '/1.15/p;/1.17/p' q.txt

/pattern/,x                 #打印从与pattern的匹配行到x号之间的行
sed -n '/1.15/,5p' q.txt

x,/pattern/                 #打印从x到与pattern匹配行之间的行
sed -n '2,/1.17/p' q.txt

x,y!                        #查询不包含x到y行号的行

r                			#从另一个文件中读文件;
w                			#将文本写入到一个文件;
y                			#变换字符;
q             				#第一个模式匹配完成后退出;
l                			#显示与八进制ASCII码等价的控制字符;
{}              			#在定位行执行的命令组;
p                			#打印匹配行;
=                			#打印文件行号;
a\              			#在定位行号之后追加文本信息;
sed '/root/aword' q.txt     #在q.txt查找root所在行,并在其下一行添加word字符,a表示在其下一行添加字符串

i\              		    #在定位行号之前插入文本信息;
sed '/root/ikuo/' q.txt     #在q.txt查找root所在行,并在其下一行添加word字符,a表示在其上一行添加字符串

d                			#删除定位行;
sed '1,3d' q.txt    #删除第一到三行
sed '2,$d' q.txt    #删除第二到最后一行
sed '$d' q.txt      #删除最后一行
for i in `seq 1 4`;do sed -i  '$d' a.txt;done   #删除最后四行

c\              			#用新文本替换定位文本;
n                			#读取下一个输入行,用下一个命令处理新的行;

N                           #将当前读入行的下一行读取到当前的模式空间。
sed 'N;s/\n/ /' jfedu.txt   #合并上下两行,也即两行合并

案例:
在q.txt查找以jfedu.kuo结尾的内容并在行尾添加字符串word,jfedu.kuoword,$表示结尾标识,&在sed中表示添加
sed 's/jfedu.kuo$/&word/g' q.txt

在q.txt中查找192.168.1.15的行并在行首添加kuo内容kuo192.168.1.15
sed '/192.168.1.15/s/^/&kuo/' q.txt
 
 在q.txt中查找192.168.1.15行并在行首添加1.内容。全文搜索www.jd.com结尾内容并在www.jd.com出添加.内容
sed -e  '/192.168.1.15/s/^/&1./' -e 's/www.jd.com$/&./g' q.txt
sed  -e  '/www.jd.com/s/^/&1./;s/www.jd.com$/&./g'  q.txt

sed读取变量,变量替换。双引号注意。(测试读取系统自带变量会报错)
WEBSITE=www.adamkuo.com
sed "s/www.jd.com/$WEBSITE/g" q.txt

修改Selinux策略enforcing为disabled,查找/SELINUX/行,然后将其行enforcing值改成disabled、!s表示不包括SELINUX行
sed  -i   '/SELINUX/s/enforcing/disabled/g' /etc/selinux/config
sed  -i   '/SELINUX/!s/enforcing/disabled/g' /etc/selinux/config

在结果前面加上行号
for i in $(seq `cat /etc/passwd|wc -l`);do echo  -n $i")";sed -n "$i"p /etc/passwd;done
1)root:x:0:0:root:/root:/bin/bash
2)bin:x:1:1:bin:/bin:/sbin/nologin

awk(行级文本高效处理工具)

AWK基本原理是逐行处理文件中的数据,查找与命令行中所给定内容相匹配的模式,如果发现匹配内容,则进行下一个编程步骤,如果找不到匹配内容,则继续处理下一行。其语法参数格式为,AWK常用参数、变量、函数详解如下:
awk 'pattern + {action}' file
1. awk基本语法参数
单括号''为了和shell命令区分开
大括号{}表示一个命令分组
pattern是一个过滤器,表示匹配pattern条件的行才能进行action处理
action是处理动作,常见动作为print
使用#作为注释,pattern和action可以只有其一,但不能两者都没有

2. awk内置变量详解
FS分隔符,默认是空格
OFS输出分隔符
NR当前行数,从1开始
NF表示一共有多少列,也可以说最后一个字段
$0当前记录
$1-$n当前记录第n个字段(列)

3. awk内置函数详解
gsub(r,s):在$0中用s代替r
index(s,t):返回s中t的第一个位置
length(s):s的长度
match(s,r):s是否匹配r
split(s,a,fs):在fs上将s分成序列a
substr(s,p):返回s从p开始的子串

4. awk常用操作符,运算符及判断符
	++ --       增加与减少( 前置或后置);
	^ **        指数( 右结合性);! + -       非、一元(unary) 加号、一元减号;
	+ - * / %   加、减、乘、除、余数;< <= == != > >=  			数字比较;&&                     	    逻辑and;||                    		逻辑or;= += -= *= /= %= ^= **= 	赋值。

5. awk与流程控制语句
if(condition){}else{}
while{}
do{}while(condition)
for(inif;condition;step){}
break/continue
案例
1. awk打印硬盘设备名称,默认以空格为分割
df -h | awk '{print $1}'

2. awk以空格、冒号、\t、分号为分割
awk -F'[:\t;]' '{print $1}' q.txt

3. awk以冒号分割,打印第一列,同时将内容追加到/tmp/awk.log下
awk -F: '{print $1}' q.txt >> /tmp/awk.log
awk -F: '{print $1>>"/tmp/awk.log"}' q.txt

4. 打印文件中的第三行至第五行,NR表示打印行,$0表示文本所有域
awk 'NR==3,NR==5 {print $1}' q.txt
awk 'NR==3,NR==5 {print $0}' q.txt
awk -F':' 'NR==3,NR==5 {print}' /etc/passwd

5. 以空格分割,打印文件中第三行和第五行的第一列与最后一列
awk -F' ' 'NR==3 {print $1,$NF};NR==5 {print $1,$NF}' q.txt

6. 打印倒数第二列
awk '{print $(NF-1)}' q.txt

7. 逐行显示每行有多少列
awk '{print NF}' q.txt

8. 显示文件的行数(print NR)
awk '{print NR}' q.txt

9. 显示文件的行数以及文件内容
awk '{print NR,$0}' q.txt

10. awk打印网卡ip
ifconfig ens33 | grep broad | awk -F' ' '/192.168/ {print $2}'

11.打印文件中字符长度大于80的行号和内容
awk 'length($0)>40 {print NR,$0}' q.txt
8 jfed;u.net test35   akuo.net: TTTTT;  jfedu.kuo

12. awk引用shell变量,使用-v或者双引号+单引号即可
awk -v STR=hello '{print STR,$NF}' q.txt

13. 在内容后添加某些内容,如果为双引号,则awk中是添加字符内容
awk '/1.15/ {print $1,"adamkuo"}' q.txt
192.168.1.15 adamkuo

14. awk以冒号切割,打印第一列同时只显示前五行
awk -F: 'NR<=5 {print $1}' /etc/passwd
awk -F: 'NR==1,NR==5 {print $1}' /etc/passwd
awk  -F:  'NR>=1&&NR<=5  {print $1}'  /etc/passwd

15.awk指定文件第一列的总和
a.txt
4 5 6
3 2 1
cat a.txt|awk '{sum+=$1}END{print sum}'
awk里边变量调用的话不用加$符号

16.awk NR行号除以2余数为0则跳过该行,继续执行下一行,打印在屏幕
awk -F: 'NR%2==0{next} {print NR,$1}' /etc/passwd

17.跳过偶数,打印技术
awk -F' ' 'NR%2==1  {print NR,$1}' q.txt
awk -F' ' 'NR%2==0{next} {print NR,$1}' q.txt

18.awk添加自定义字符
ifconfig ens33|grep "broad"|awk '{print "ip_"$2}'

19. awk与if组合实践,判断数字比较
echo 3 2 1|awk '{if (($1>$2)){print $2}else{print $1}}'
echo 3 2 1|awk '{if (($1>$2)){print $2}}'

20. awk分析nginx访问日志的状态码404、502等错误信息页面,统计次数大于20的IP地址
awk '{if ($9~/502|499|500|503|404/) print $1,$9}' access.log|sort|uniq -c|sort -nr|awk '{if($1>20) print $2}'

21. 匹配q.txt中行内容包含2|4|5|6的
awk '$NR ~ /2|4|5|6/ {print NR,$0}' q.txt
awk '{if ($NF ~ /2|4|5|6/){print $0}fi}' q.txt

22. 打印tcp开头的内容的最后一列,用sort进行从小到大排序(sort –nr从大到小),uniq去重,uniq –c去重后将重复的值显示到最前边
netstat -an | awk '/tcp/ {print $NF}' | sort|uniq -c

grep工具(全面搜索正则表达式)

grep是一种强大的文本搜索工具,它能使正则表达式搜索文本,并把匹配的行打印出来。
Unix/Linux的grep家族包括grep、egrep和fgrep,其中egrep和fgrep的命令跟grep有细微的区别,egrep是grep的扩展,支持更多的re元字符。
目前Linux操作系统默认使用GNU版本的grep。它功能更强,可以通过-G、-E、-F命令行选项来使用egrep和fgrep的功能。

grep -option 'word' filename
-a                   以文本文件方式搜索,默认为-a不用是默认
-c                   计算找到的符合行的次数
grep -c 'root' q.txt   #匹配内容为root得总行数

-i                   忽略大小写
grep -i 'root' q.txt   #忽略大小写查询包含root得内容

-n                   顺便输出行号
grep -n 'root' q.txt     #打印搜索出来包含root得行,并显示行号1:   2:
1:192.168.1.14 root 1232456 2
2:192.168.1.15 root 1232456 3

-v                   反向选择
grep -v 'root' q.txt     #查询不包含root得行内容

-h                   查询多文件时不显示文件名
-l                   查询多文件时只输出包含匹配字符的文件名和-r配合使用
-s                   不显示不存在或匹配无文本的错误信息
-E                   允许使用egrep扩展模式匹配
-w                   匹配一个词组

案例

查询以字符test开头,接5或者3的行
grep "test[53]" jfedu.txt

显示输出行首不是test得行;^表示以字符开头,[^]除括号中以外得任意字符,表示取反
grep '^[^test]' q.txt

匹配字符以T或者t开头得行内容
grep '[Tt]e' q.txt

匹配T后三个任意字符,紧接53的字符内容行
grep 'T...53' q.txt
www.jd.com  Test53  www.baidu.com

匹配连续出现两次T的行
grep 'T\{2\}' q.txt

匹配连续出现两次T以上的行
grep 'T\{2,\}' q.txt

匹配连续出现两次到三次T的行
grep 'T\{2,3\}' q.txt

打印空行所在的行号
grep -n '^$' q.txt

不匹配文中的空行和#行(必须带E参数,否则无法使用|参数)
grep -vE '^$|#' q.txt

匹配IPV4地址
grep --color -E "\<([0-9]{1,3}\.){3}([0-9]{1,3})\>" q.txt

搜索文件及文件夹下包含该字符的内容文件并修改所有包含该字符文件的内容
for i in $(grep -rl '1.177' *);do sed -i 's/1.177/1.188/g' $i;done
for i in $(find . -type f);do sed -i 's/1.188/1.199/g' $i;done

通配符类型

*						0个或者多个字符、数字;
?						匹配任意一个字符;
#						表示注解;
|						管道符号;
;						多个命令连续执行;
&						后台运行指令;
!						逻辑运算非;
[ ]						内容范围,匹配括号中内容;
{ }						命令块,多个命令匹配。

正则表达式

*						前一个字符匹配0次或多次;
.						匹配除了换行符以外任意一个字符;
.*						代表任意字符(1个多个+);
^						匹配行首,即以某个字符开头;
$						匹配行尾,即以某个字符结尾;
\(..\) 					标记匹配字符;(常规匹配grep 192 list.txt)
[]						匹配中括号里的任意指定字符,但只匹配一个字符;
[^]						匹配除中括号以外的任意一个字符;括号内容取反
\						转义符,取消特殊含义;
\<word>                 锚定单词的开始和结束,类似于-w
\< 						锚定单词的开始;从锚定词开始
\> 						锚定单词的结束;到锚定词结束
{n}						匹配字符出现n次;
{n,}					匹配字符出现大于等于n次;
{n,m}					匹配字符至少出现n次,最多出现m次;
\w 						匹配文字和数字字符,不匹配符号;
\W 						\w的反置形式,匹配一个或多个非单词字符,匹配符号;
\b 						单词锁定符;
\s						匹配任何空白字符;
\d						匹配一个数字字符,等价于[0-9]。需配合-P(扩展参数)使用

Shell数组编程

定义数组一般以小括号的方式来定义,数组的值可以随机指定,如下为一维数组的定义、统计、引用和删除操作
1. 一维数组定义及创建
TEST=(
	test1
	test2
	test3
)
LAMP=(http php php-devel php-mysql mysql mysql-devel)
2. 数组下标一般从0开始,引用数组的方法
echo ${TEST[0]}    引用第一个数组变量,结果为test1
echo ${TEST[@]}    显示数组的所有参数
echo ${#TEST[@]}   显示数组参数个数
echo ${#TEST[0]}   显示第一个数组参数字符长度
echo ${TEST[@]:0}    打印数组所有值
echo ${TEST[@]:0:1}  打印数组所有值后的一个值test1
echo ${TEST[@]:0:2}  打印数组所有值后两个值test1 test2
echo ${TEST[@]:1:2}  打印数组下标1也就是第二个值后的两个值

3. 数组替换操作
TEST=([0]=www1 [1]=www3)   会将以前的都覆盖,重新赋值。以前多的也就没了
echo ${TEST[@]/www1/www11}    修改单个数组值,将数组www1值修改为www11

4. 数组删除操作
unset TEST[0]   删除数组第一个值
unset TEST      删除整个数组

Shell脚本案例

Shell脚本企业案例一,网卡bond绑定脚本
#!/bin/bash
#Auto Make KVM Virtualization
#Auto config bond scripts
#By author jfedu.net 2017
eth_bond()
{
NETWORK=(
  HWADDR=`ifconfig eth0 |egrep "HWaddr|Bcast" |tr "\n" " "|awk '{print $5,$7,$NF}'|sed -e 's/addr://g' -e 's/Mask://g'|awk '{print $1}'`
  IPADDR=`ifconfig eth0 |egrep "HWaddr|Bcast" |tr "\n" " "|awk '{print $5,$7,$NF}'|sed -e 's/addr://g' -e 's/Mask://g'|awk '{print $2}'`
  NETMASK=`ifconfig eth0 |egrep "HWaddr|Bcast" |tr "\n" " "|awk '{print $5,$7,$NF}'|sed -e 's/addr://g' -e 's/Mask://g'|awk '{print $3}'`
  GATEWAY=`route -n|grep "UG"|awk '{print $2}'`
)
cat >ifcfg-bond0<<EOF
DEVICE=bond0
BOOTPROTO=static
${NETWORK[1]}
${NETWORK[2]}
${NETWORK[3]}
ONBOOT=yes
TYPE=Ethernet
NM_CONTROLLED=no
EOF

Shell脚本企业案例二,定义IPv4值
#!/bin/bash
#auto Change ip netmask gateway scripts  
#By author jfedu.net 2017
ETHCONF=/etc/sysconfig/network-scripts/ifcfg-eth0
HOSTS=/etc/hosts
NETWORK=/etc/sysconfig/network
DIR=/data/backup/`date +%Y%m%d`
NETMASK=255.255.255.0
echo "----------------------------"
count_ip(){
        count=(`echo  $IPADDR|awk  -F.  '{print $1,$2,$3,$4}'`)
        IP1=${count[0]}
        IP2=${count[1]}
        IP3=${count[2]}
        IP4=${count[3]}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值