Shell编程四剑客
Shell编程四剑客包括:find、sed、grep、awk
Find工具(系统中查找文件)
四剑客Find工具主要用于操作系统文件、目录的查找,其语法格式为:
find path -option [ -print ] [ -exec -ok command ]
{} \
常用option参数如下:
-name 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]
例: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
find /data/ -mtime +30 -name "*.txt"
find /data/ -mtime 30 -name "*.txt"
find /data/ -mtime -30 -name "*.txt"
find /opt/ -mtime -30 -name "*.txt" | xargs ls -l
-atime -n +n
-ctime -n +n
-maxdepth
例:find /opt -maxdepth 1
find案例:
find /opt -name "*.txt" -size +5k -exec cp {} /tmp/dd/ \;
find /opt/sh -name "*.sh" -size +2k -perm 644 -exec rm -rf {} \;
find /opt/sh -name "*.sh" -mtime +30 -size +1k -exec cp {} /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
sed 's/old/new/g' q.txt
sed '1,3s/old/new/g' q.txt
sed '3s/old/new/g' q.txt
sed '/net/s/jfedu/kuo/g' q.txt
sed '1s/root/kuo/g;3s/root/adamin/g' q.txt
sed -e '1s/old/new/g' –e '3s/old/new/g' jfedu.txt
x
sed -n '3p' q.txt
x,y
sed -n '1,3p' q.txt(-n静默显示,只显示匹配到得)
sed -n '1p;$p' q.txt
xp;yp
sed -n '1p;3p' q.txt
/pattern/
sed -n '/1.17/p' q.txt
/pattern/,/pattern/
sed -n '/1.15/,/1.17/p' q.txt
/pattern/;/pattern/
sed -n '/1.15/p;/1.17/p' q.txt
/pattern/,x
sed -n '/1.15/,5p' q.txt
x,/pattern/
sed -n '2,/1.17/p' q.txt
x,y!
r
w
y
q
l
{}
p
=
a\
sed '/root/aword' q.txt
i\
sed '/root/ikuo/' q.txt
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
使用
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
-i 忽略大小写
grep -i 'root' q.txt
-n 顺便输出行号
grep -n 'root' q.txt
1:192.168.1.14 root 1232456 2
2:192.168.1.15 root 1232456 3
-v 反向选择
grep -v 'root' q.txt
-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
不匹配文中的空行和
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绑定脚本
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值
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]}
}