# Shell 常用命令 - grep-sed

# 1.grep 正则表达式介绍

# 1.1 什么是正则表达式

以特定的符号 "表示一组数字或字母的",一种规则

# 1.2 为何需要正则表达式
  • 在工作中,我们时刻面对着大量的日志,程序,以及命令的输出。迫切的需要过滤我们需要的一部分内容,甚至是一个字符串。
  • 比如:现在有一个上千行的文件,我们仅需要其中包含 “ERROR” 的行,怎么办?此时就需要使用到正则表达式的规则来筛选想要的内容。
# 1.3 正则表达式注意事项
  • 正则表达式应用非常广泛,存在于各种编程语言中。
  • 正则表达式和 Linux 的通配符以及特殊字符是有区别的 。
  • 要想学好 grep、sed、awk 首先就需要对正则表达式有一定的了解,只有了解了规则,才能灵活的运用。
# 1.4 正则表达式规则语法

1. 正则表达式

\:转义符,将特殊字符进行转义,忽略其特殊意义
^:匹配行首,匹配字符串的开始
$:匹配行尾,匹配字符串的结尾
^$:表示空行
.:匹配除换行符\n之外的任意单个字符 
[]:匹配包含在[字符]之中的任意一个字符 [a|b]cd
[^]:匹配[^a]之外的任意字符 
[ - ]:匹配[]中指定范围内的任意一个字符 [a-z] | [0-9]
?:匹配之前的项1次或者0次 
+:匹配之前的项1次或者多次 [0-9]+
*:匹配之前的项0次或者多次 .* 
():匹配表达式,创建一个用于匹配的子串 grep "ab(c|d)"
{n}:匹配之前的项n次,n是可以为0的正整数 grep "[0-9]{1,3}"
{n,}:之前的项至少需要匹配n次
{n,m}:指定之前的项至少匹配n次,最多匹配m次,n<=m
|:交替匹配,|两边的任意一项ab(c|d)匹配abc或abd
\<\>\b锚定词首与词尾, \<grep\> ,匹配所有包含grep字符的行,如果出现grepa是不会被匹配

2. 特殊字符

[[:space:]]:匹配空格
[[:digit:]]:匹配[0-9]
[[:lower:]]:匹配[a-z]
[[:upper:]]:匹配[A-Z]
[[:alpha:]]:匹配[a-Z]

3.grep 常用选项

选项作用说明
-i忽略大小写(大小写不敏感匹配)。
-ogrep -ogrep 命令中一个非常实用的选项,其作用是只输出匹配到的内容本身(而非整行),且每个匹配项单独占一行。
-v反向匹配,只输出不匹配模式的行。
-n显示匹配行的行号。
-l只显示包含匹配模式的文件名(而非具体行内容)。
-r / -R递归搜索目录下的所有文件( -R 会跟随符号链接)。
-w匹配完整单词(避免部分匹配,如搜索 "cat" 不会匹配 "category")。
-c统计匹配的行数(而非显示内容)。
-E使用扩展正则表达式(支持 ``、 () 等元字符,无需转义),等价于 egrep
-F按固定字符串匹配(不解析正则表达式),等价于 fgrep
--color=auto为匹配到的内容添加颜色高亮(多数系统默认开启)。

4. 准备如下文件,然后进行正则表达式规则验证。

[root@client ~]# cat test.txt 
I am xuyong teacher!
I teach linux.
test
I like badminton ball ,billiard ball and
chinese chess!
my blog is
http://xuyonglinux.blog.51cto.com
our site is http://www.ixuyong.cn
my qq num is 572891887.
not 572891888887.

进行如下场景验证:

#1. 过滤以 m 开头的行
[root@client ~]# grep "^m" test.txt 
#2. 排除空行,并打印行号
[root@client ~]# grep -vn "^$" test.txt 
#3. 匹配任意一个字符,不包括空行
[root@client ~]# grep "." test.txt
#4. 匹配所有内容
[root@client ~]# grep ".*" test.txt
#5. 匹配以点结尾的
[root@client ~]# grep "\.$" test.txt 
#6. 匹配有 a 或 b 或 c 的行
[root@client ~]# egrep "[a|b|c]" test.txt 
#7. 匹配数字所在的行
[root@client ~]# egrep "[0-9]" test.txt
#8. 匹配所有小写字母
[root@client ~]# egrep "[a-z]" test.txt 
#9. 匹配包含 5 个 8 的行
[root@client ~]# egrep "[8]{5}" test.txt

# 2.grep 正则表达式案例

# 2.1 提取服务器网卡地址

需求:使用 grep 正则方式方式,提取 eth0 的 IP 地址;

[root@client ~]# ifconfig eth0 | grep "^.*inet " | egrep -o "[0-9]{2,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
[root@client ~]#  ifconfig eth0 | grep "^.*inet " | egrep -o "[[:digit:]]{2,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}"
# 2.2 过滤空行与 #开头的行

需求:使用 grep 正则表达式方式,排除 nginx 日志文件的空行和 #号开头的行。

[root@client ~]# egrep -v "(^#|^$|^[[:space:]]+#)" nginx.conf
# 2.3 匹配日志中 http 版本

需求:使用 grep 正则表达式方式,匹配 nginx 日志中的 http3.0 http3.1 http2.1 http2.0

[root@client ~]# cat test1.txt 
[27/Sep/2021:09:55:06 +0800]"GET/HTTP/1.0"200 4"_""curl/7.29.0"
:1[27/Sep/2021:09:55:18+0800] "GET/HTTP/1.1""2004"_""curl/7.29.0"
:1[27/Sep/2021:09:55:21 +0800] "GETT/HTTP/1.1"20044"_""curl/7.29.0"
::1[27/Sep/2021:09:55:25+0800]]"GET/HTTP/2.O"20044"_""curl/7.29.0"
::1[27/Sep/2021:09:55:255+0800]"GET/HTTP/2.0"200 4"_""curl/7.29.0""
:1[27/Sep/2021:09:55:255+0800]“GET/HTTP/2.1"2004"_""curl/7.29.0"
::1[27/Sep/2021:09:55:265+0800]“GETHTTP/1.1""200 4"_""curl/7.29.0"
::1[27/Sep/2021:09:55:265+0800]“GETHTTP/3.1" 200 4 "-" "curl/7.29.0"
:1[27/Sep/2021:09:55:265+0800]"GET/HTTP/3.1"200 4"_""curl/7.29.0"
[27/Sep/2021:09:55:265+0800]“GETHTTP/3.0"200 4"_""curl/7.29.0"
[root@client ~]# grep -io "http/[1|2|3]\.[0|1|2]" test1.txt 
HTTP/1.0
HTTP/1.1
HTTP/1.1
HTTP/2.0
HTTP/2.1
HTTP/1.1
HTTP/3.1
HTTP/3.1
HTTP/3.0
# 2.4 过滤无注释的配置文件

需求:使用 grep 正则表达式方式,匹配 zabbix_agentd.conf 配置文件中所有已启用的配置。

[root@client ~]# egrep -v "^#|^$" zabbix_agentd.conf
[root@client ~]# grep '^[a-Z]' zabbix_agentd.conf
# 2.5 匹配用户手机号是否合法

需求:使用 grep 正则表达式方式,匹配 133、152、166、135 开头的手机号码。

[root@client ~]# cat grep01.sh 
#!/bin/bash
read -p "请输入你要测试的手机号[[ 133 | 152 | 166 ]: " Action
if [[ $Action =~ [0-9]{11}$ ]];then
	# 判断开头是否为 133 152
	if [[ $Action =~ ^(133|152|166)[0-9]{8}$ ]];then
		echo "$Action 是合法手机号...."
	else
		echo "$Action 手机号输入错误"
	fi
else
	echo "$Action 目前属于非法手机号..."
fi
# 2.6 匹配用户邮箱是否合法

需求:使用 grep 正则表达式方式,匹配 qq、163、sina 的 email 地址。

  • 前缀:数字 | 字母 组成方式 (长度,不可以超过 16)
  • @ 正常出现
  • qq | sina | foxmail | 163 | gmail 固定的字段
  • .com .cn .org 不做控制
[root@client ~]# cat email.sh 
#!/usr/bin/bash
read -p "请输入找回密码的邮箱: " Action
Action_pre=${Action%@*}
# 比对前缀的长度是否超过 16
if [ ! ${#Action_pre} -le 16 ];then
	echo "你输入的邮箱长度太长"
	exit
fi
# 匹配
	# (0-9 | a-z )+    
	# 纯数字
	# 数字 + 字母
	# 纯字母
	# 字母 + 数字
if [[ $Action =~ ^([0-9]|[a-z])+|@(qq|sina|163)\..+$ ]];then
	echo "$Action 邮件已经发送,请登录邮箱点击链接找回密码"
else
	echo "$Action 不符合系统预定的邮箱规则,请重新尝试"
fi
# 2.7 正则匹配文件中的域名

需求:现在有如下文件,希望通过如下方式进行匹配:grep " 正则 .shop.oldxu.com

[root@client ~]# cat rege.txt 
xxt-demo.shop.oldxu.com
xxt-demoadmin.shop.oldxu.com
abc.shop.oldxu.com
abcadmin.shop.oldxu.com
123.shop.oldxu.com
abc123.shop.oldxu.com
bbb.admin.oldxu.com
bbb-ccc.admin.oldxu.com
bbb-ccc-ddd.admin.oldxu.com
bbb-ccc-ddd.shop.oldxu.com
[root@client ~]# egrep "^([a-z]|-)+\.(shop|admin)\.oldxu\.com" rege.txt
xxt-demo.shop.oldxu.com
xxt-demoadmin.shop.oldxu.com
abc.shop.oldxu.com
abcadmin.shop.oldxu.com
bbb.admin.oldxu.com
bbb-ccc.admin.oldxu.com
bbb-ccc-ddd.admin.oldxu.com
bbb-ccc-ddd.shop.oldxu.com
[root@client ~]# egrep "^([a-z]{1,}-[a-z]{1,}|[a-z]{1,}|admin)\.shop\.oldxu\.com" rege.txt
xxt-demo.shop.oldxu.com
xxt-demoadmin.shop.oldxu.com
abc.shop.oldxu.com
abcadmin.shop.oldxu.com

# 3.sed 文本处理

# 3.1 sed 基本介绍
  • sed (Stream Editor) 流编辑器,能够对标准输出或文件进行逐行处理。
  • 简单来说,sed 可以实现对文件的增、删、查、改。
# 3.2 sed 工作模式

sed 读取文件一行,存放在缓存区,然后处理,最后输出。

# 3.3 sed 基础语法

第一种形式:stdout | sed [option] "pattern command"

  • option: 选项
  • pattern:匹配 sed '/^root/' |grep
  • command: 动作 p,d, c , s###g , r,w,i,a

第二种形式: sed [option] "pattern command" file

# 3.4 sed 常用选项
选项含义
-n只打印匹配的行(取消文件的默认输出)
-e允许多项编辑
-f编辑动作保存在文件,指定文件才执行
-r支持扩展正则表达式
-i直接变更文件内容

1.sed 相关示例文件

[root@client ~]# cat file.txt
I love shell
I love SHELL
This is test file
# 3.4.1 -n 选项

sed -n 用于取消默认输出

[root@client ~]# sed -n '/shell/p' file.txt 
I love shell
# 3.4.2 -e 选项

sed -n 用于多项编辑

[root@client ~]# sed -n -e '/shell/p' -e '/SHELL/p' file.txt
I love shell
I love SHELL
# 3.4.3 -f 选项

sed -f 编辑动作保存在文件,指定文件才执行将 pattern 写入文件中

[root@client ~]# cat edit.sed
/shell/p

通过 sed -f 执行

[root@client ~]# sed -n -f edit.sed file.txt 
I love shell
# 3.4.4 -r 选项

sed -r 支持扩展正则表达式

[root@client ~]# sed -rn '/shell|SHELL/p' file.txt 
I love shell
I love SHELL
# 3.4.5 sed 实战

sed 取 ip 地址

[root@client ~]# ifconfig eth0 | sed -n '/inet /p' | sed -r 's#(^.*et )(.*)(net.*$)#\2#g'
192.168.40.10
# 3.5 sed pattern 过滤

命令格式:sed [option] '/pattern/command'file

# 3.5.1 pattern 命令格式
匹配模式含义
10command匹配第 10 行
10,20command匹配从第 10 行开始,到第 20 行结束
10,+5command匹配从第 10 行开始,到第 16 行结束
/pattern1/,/pattern2/command匹配到 pattern1 的行开始,到 匹配到 pattrn2 的行结束
10,/pattern1/command匹配从第 10 行开始,到匹配到 pattern1 的行结束
# 3.5.2 pattern 命令示例

1. 示例:指定行号。

#打印 passwd 文件的第 10 行
[root@client ~]# sed -n '10p' passwd 
operator:x:11:0:operator:/root:/sbin/nologin

2. 示例:指定起始行号和结束行号

#打印 passwd 文件的 10 到 20 行
[root@client ~]# sed -n '10,20p' passwd 
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin

3. 指定起始行号,然后后面 N 行

#打印 passwd 文件中从第 1 行开始,往后面加 5 行的内容
[root@client ~]# sed -n '1,+5p' 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

4. 正则表达式匹配(打印 passwd 文件中以 root 开头的行)

[root@client ~]# sed -n '/^root/p' passwd
root:x:0:0:root:/root:/bin/bash

5. 从匹配到 pattern1 的行,到匹配 pattern2 的行(打印 passwd 文件第一个匹配到以 bin 开头的行,到第二个匹配到以 ftp 的行)

[root@client ~]# sed -rn '/^bin/,/^ftp/p' passwd 
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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

6. 从指定的行号开始匹配,直到匹配到 pattern1 的行

#打印 passwd 文件中从第 11 行开始匹配,直到以 ^ftp 开头的行结束
[root@client ~]# sed -n '11,/^ftp/p' passwd 
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
# 3.5.3 pattern 章节练习
#1. 打印 /etc/passwd 中第 20 行
sed -n '20p' /etc/passwd
#2. 打印 /etc/passwd 中从第 8 行开始,到第 15 行结束的内容
sed -n '8,15p' /etc/passwd
#3. 打印 /etc/passwd 中从第 8 行开始,然后 + 5 行结束的内容
sed -n '8,+5p' /etc/passwd
#4. 打印 /etc/passwd 中开头匹配 bin 字符串的内容
sed -n '/^bin/' /etc/passwd
#5. 打印 /etc/passwd 中开头为 root 的行开始,到开头为 ftp 的行结束的内容
sed -n '/^root/,/ftp/p' /etc/passwd
#6. 打印 /etc/passwd 中第 8 行开始,到含有 /sbin/nologin 的内容的行结束内容
sed -n '8,/\/sbin\/nologin/p' /etc/passwd
[root@client ~]# sed -n '/^\[base\]/,/\[.*/p' /etc/yum.repos.d/CentOS-Base.repo | sed -r '/^\[|^#/d'
name=CentOS-$releasever - Base - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/os/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
# 3.6 sed 追加命令
# 3.6.1 追加命令格式
编辑命令含义
a行后追加内容 append
i行前追加内容 insert
r读入外部文件,行后追加
w将匹配行写入外部文件
# 3.6.2 追加命令示例

1. 匹配 /bin/bash 的行,在其行后面添加一行内容。

[root@client ~]# sed -i '/^bin/a ok' passwd

2. 以 /bin 开头的行到已 sshd 开头的行,前面添加一行。

[root@client ~]# sed -i '/^bin/,/^sshd/i OKOK' passwd

3. 指定给文件的 30 行添加一行内容。

[root@client ~]# sed -i '30i listen 80' passwd

4. 将 list.txt 文件中的内容,追加到匹配模式的行后面

[root@client ~]# sed -i '/root/r list.txt'

5. 匹配 /bin/bash 所有的行,将其保存至 /tmp/login.txt 文件中

[root@client ~]# sed '/\/bin\/bash/w /tmp/login.txt' passwd

6.ssh 配置文件 /etc/ssh/sshd_config ,端口改为 6666

[root@client ~]# sed -i '/#Port/a port 666' /etc/ssh/sshd_config
# 3.6.3 追加章节练习
1)passwd文件第10行后面追加 "Add Line"
sed -i '10a Add Line'
2)passwd文件第10行到第20行,每一行后面都追加"Test Line"
sed -i '10,20a Test Line' passwd
3)passwd文件匹配到/bin/bash的行后面追加"Insert Line"
sed -i '10a Insert Line'
4)passwd文件匹配到以bin开头的行,在匹配的行前住家 "Add Line Before"
sed -i '/^bin/i Add Line Before'
5)passwd文件每一行前面都追加 "Insert LineBefore"
sed '/^/i Insert Line Before' passwd
6)将/etc/fstab文件的内容追加到passwd文件的第10行后面
sed -i '10r /etc/fstab' passwd 
7)将/etc/inittab文件内容追加到passwd文件匹配/bin/sync行的后面
sed -i '/\/sbin\/nologin/r /etc/inittab' passwd
8)将/etc/hosts文件内容追加到passwd文件中10行的后面
sed -i '/\/sbin\/nologin/r /etc/inittab' passwd
9)将passwd文件匹配到/bin/bash的行追加到/tmp/sed.txt文件中
sed '/\/bin\/bash/w /tmp/sed.txt' passwd
# 3.7 sed 删除命令
# 3.7.1 删除命令格式
编辑命令含义
1d删除第 1 行的内容
1,5d删除 1 行到 5 行的内容
2,+5d删除 2 行以及往下的 5 行的内容
/pattern1/d删除每行中匹配到 pattern1 的行内容
/pattern1/,/pattern2/d删除匹配到 pattern1 的行直到匹配到 pattern2 的所有行内容
/pattern1/,10d删除匹配到 pattern1 的行到 10 行的所有行内容
10,/pattern1/d删除第 10 行直到匹配到 pattern1 的所有内容
# 3.7.2 删除命令示例
#1. 删除 passwd 文件中第 1 行内容
sed '1d' passwd
#2. 删除 passwd 文件中第 1 行到第 5 行的内容
sed '1,5d' passwd
#3. 删除 passwd 文件中第 2 行以及往下的 5 行内容
sed '2,+5d' passwd
#4. 匹配 /sbin/nologin 结尾的行,然后进行删除
sed '/\/sbin\/nologin$/d' passwd
#5. 匹配以 sshd 开头的行,到 rpc 开头的行删除
sed '/^sshd/,/^rpc/d' passwd
#6. 删除 vsftpd 配置文件以 # 号开头的行,以及空行
#删除配置文件中 #号开头的注释行,如果碰到 tab 或空格是无法删除
sed '/^#/d' file
#删除配置文件中含有 tab 键的注释行
sed -r '/^[ \t]*#/d' file
#删除无内容空行
sed -r '/^[ \t]*$/d' file
# 3.7.3 删除章节练习
#1. 删除 /etc/passwd 中的第 15 行
sed '15d'
#2. 删除 /etc/passwd 中的第 8 行到第 14 行的所有内容
sed '8,14d'
#4. 删除 /etc/passwd 中以 /sbin/nologin 结尾的行
sed '/\/sbin\/nologin$/d'
#4. 删除 /etc/passwd 中以 bin 开头的行,到以 ntp 开头的行的所有内容
sed '/^bin/,/^ntp/d'
#5. 删除 /etc/passwd 中第 3 行到以 ftp 开头的所有行内容
sed '3,/^ftp/d'
#6. 典型需求:删除 Nginx 配置文件中所有的注释以及空行
sed -i '/^#|^$/d'
# 3.8 sed 修改命令
# 3.8.1 修改命令格式
编辑命令含义
1s/old/new/替换第 1 行内容 old 为 new
1,10s/old/new/替换 1 行到 10 行的内容 old 为 new
1,+5s/old/new/替换 1 行到 6 行的内容 old 为 new
/pattern1/s/old/new/替换匹配 pattern1 的内容 old 为 new
/pattern1/,/pattern2/s/old/new/替换匹配到 pattern1 的行直到匹配到 pattern2 的所有行内容 old 为 new
10,/pattern1/s/old/new/替换第 10 行直到匹配到 pattern1 的所有行内容 old 为 new
# 3.8.2 修改命令示例
#1. 修改 passwd 文件第 1 行中第一个 root 为 ROOT
sed -i '1s/root/ROOT/' passwd
#2. 修改 passwd 文件中第 5 行到第 10 行中所有的 /sbin/nologin 为 /bin/bash
sed -i '5,10s/\/sbin\/nologin/\/bin\/bash/' passwd
sed -i '5,10s#/sbin/nologin#/bin/bash#' passwd
#3. 修改 passwd 文件中匹配到 /sbin/nologin 的行,将匹配到行中的 login 为该大写的 LOGIN
sed -i '/\/sbin\/nologin/s#login#LOGIN#g' passwd
sed -i '/\/sbin\/nologin/s/login/LOGIN#g' passwd
#4. 修改 passwd 文件中从匹配到以 root 开头的行,到匹配到行中包含 bin 的行
sed -i '/^root/,/^bin/s/bin/BIN/g' passwd
#5. 修改 SELINUX=enforcing 修改为 SELINUX=disabled(可以使用 c 替换方式)
sed -i '/^SELINUX=/c SELINUX=disabled' selinux
#6. 将 nginx.conf 配置文件添加注释
sed -i 's/^/# /' nginx.conf
#7. 使用 sed 提取 eth0 网卡的 IP 地址
ifconfig eth0 | sed -rn '2s/^.*et //p' | sed -rn 's/ ne.*//p'
ifconfig eth0 | sed -nr '2s/(^.*et) (.*) (net.*)/\2/p'
# 3.9 sed 脚本实践
# 3.9.1 分析 Ansible 主机清单实践

需求: 处理一个 ansible 的 invtory 主机清单。

  • 1. 输出主机组,一对 [ ] 为一个主机组。
  • 2. 输出每个主机组下的主机总个数。

执行结果:

[root@client ~]# sh example.sh
1: web01: 有 2 台主机
2: web02: 有 12 台主机

1. 主机清单文件

[root@client ~]# cat hosts
[dnsservers]
172.16.1.91
172.16.1.92
[routes]
172.16.1.200
[lbservers]
172.16.1.3
172.16.1.4
[proxyservers]
172.16.1.5
172.16.1.6
[webservers]
172.16.1.7
172.16.1.8 
172.16.1.9
[dbservers]
172.16.1.51
[redisservers]
172.16.1.41
[nfsservers]
172.16.1.32
[backupservers]
172.16.1.31

2. 需求实现

[root@client ~]# cat ansible_sed.sh 
#!/usr/bin/bash
inventory=hosts
# 获取主机组的名称的函数(有很多主机组的名称)
get_host_groups_name(){
	get_names=$(sed -n '/^\[/p' ${inventory} | sed -n 's/\[//p' | sed -n 's/\]//p')
	echo $get_names
}
# 通过拿到主机组的名称,能够提取对应的数量
get_host_number(){
	get_hosts=$(sed -n '/^\['$1'\]/,/\[.*\]/p' hosts | sed -r '/\[|^$/d' | wc -l)
	echo $get_hosts
}
get_host_ip() {
	get_ip=$(sed -n '/^\['$1'\]/,/\[.*\]/p' hosts | sed -r '/\[|^$/d' | xargs)
	echo $get_ip
}
index=1
# 遍历获取每个主机组的数量
	#1. 调用函数拿到所有的组名称
	#2. 将 webservers 赋值给 host 变量
for host in $(get_host_groups_name)
do
	# 3. 执行 get_host_number 这个函数 传递了一个参数 host  host 的结果是 webservers
	numbers=$(get_host_number $host)
	host_ip=$(get_host_ip $host)
	#  $host 对应的就是组的名称  $numbers 就是最终这个组对应的数量
	echo "${index}: 主机组名称: $host  主机数量: $numbers 对应的IP是: ${host_ip}"
	index=$[ $index +1 ]
done
# 3.9.2 分析 MySQL 配置文件实践

需求:处理一个 MySQL 配置文件的 my.cnf 文件。

  • 1. 输文件中有几个段,一对 [ ] 为一段。
  • 2. 针对每个段统计配置文件参数总个数。

脚本执行结果:

[root@client ~]# sh mysql_conf_total.sh
1: client 2
2: server 12
3: mysqld 12
4: mysqld_safe 7
5: embedded 8
6: mysqld-5.5 10
# 1 获取 [] 内容,sed -n '/^\[/p' my.cnf | sed's/\[//' | sed's/\]//'
# 2 基于 [] 内容,提取的数量;sed -n '/\[mysqld\]/,/\[.*\]/p' my.cnf | sed -r '/\[|^$|#/d' |wc -l

1.MySQL 配置文件

[root@client ~]# cat my.cnf
# this is read by the standalone daemon and embedded servers
[client]
port=3306
socket=/tmp/mysql.socket
#This For server
[server]
innodb_buffer_pool_size=8G
innodb_buffer_pool_instances=8
innodb_buffer_pool_load_at_startup=1
innodb_buffer_pool_dump_at_shutdown=1
innodb_data_file_path=ibdata1:1G:autoextend
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=32M
innodb_log_file_size=2G
innodb_log_files_in_group=2
innodb_max_undo_log_size=4G
innodb_undo_directory=undolog
innodb_undo_tablespaces=95
#this is ysqld stand alone daemon
[mysqld]
port=3306
socket=/tmp/mysql.sock
basedir=/usr/local/mysql
datadir=/data/mysql
pid-file=/data/mysql/mysql.pid
user=mysql
bind-address=0.0.0.0
sort_buffer_size=16M
join_buffer_size=16M
thread_cache_size=3000
interactive_timeout=600
wait_timeout=600
#This Form ysqld_safe
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
max_connections=1000
open_files_limit=65535
thread_stack=512K
external-locking=FALSE
max_allowed_packet=32M
#this is only for embedded server
[embedded]
gtid_mode=on
enforce_gtid_consistency=1
log_slave_updates
slave-rows-search-algorithms='INDEX_SCAN,HASH_SCAN'
binlog_format=row
binlog_checksum=1
relay_log_recovery=1
relay-log-purge=1
#mysqld configure
[mysqld-5.0]
key_buffer_size=32M
read_buffer_size=8M
read_rnd_buffer_size=16M
bulk_insert_buffer_size=64M
myisam_sort_buffer_size=128M
myisam_max_sort_file_size=10G
myisam_repair_threads=1
lock_wait_timeout=3600
explicit_defaults_for_timestamp=1
innodb_file_per_table=1

2. 需求实现

[root@client ~]# cat mysql_sed.sh 
#!/bin/bah
#1. 先定义函数,拿到 [] 中的名字
get_mysql_name() {
	sed -n '/^\[/p' my.cnf  | sed 's/\[//' | sed 's/\]//'
}
get_mysql_number() {
	sed -n '/\['$1'\]/,/\[.*\]/p' my.cnf  | sed -r '/\[|^$|#/d' |wc -l
}
index=1
for i in  $(get_mysql_name)
do
	numbers=$(get_mysql_number $i)
	echo "$index: $i         $numbers"
	index=$[ $index + 1 ]
done
此文章已被阅读次数:正在加载...更新于

请我喝[茶]~( ̄▽ ̄)~*

Xu Yong 微信支付

微信支付

Xu Yong 支付宝

支付宝