shell正则表达式

文章目录

    • 正则表达式
      • cut、sort、uniq、tr
        • cut:列截取工具
        • sort 排序
        • uniq
        • tr替换
        • 面试组合使用
      • sed
          • 1.sed 命令常见用法
          • 2.用法示例
          • (1)输出符合条件的文本(p 表示正常输出)
          • (2)删除符合条件的文本(d)
          • (3)替换符合条件的文本
          • (4)迁移符合条件的文本
          • (5)使用脚本编辑文件
          • (6)sed 直接操作文件示例
      • grep
      • awk
        • 命令格式:
          • 模糊匹配,用~表示包含,!~表示不包含
          • 逻辑运算 && ||
          • 其他内置变量的用法FS、OFS、NR、FNR、RS、ORS
          • awk高级用法
            • 定义引用变量
            • if语句:awk的if语句也分为单分支、双分支和多分支
            • awk还支持for循环、while循环、函数、数组等

正则表达式

正则表达式,又称规则表达式。(英语:Regular Expression),在代
码中常简写为 regex、regexp 或 RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
正则表达式不只有一种,而且 LINUX 中不同的程序可能会使用不同的正则表达式,如:
工具:grep sed awk egrep

正则表达式—通常用于判断语句中,用来检查某一字符串是否满足某一格式
正则表达式是由普通字符与元字符组成
普通字符包括大小写字母、数字、标点符号及一些其他符号
元字符是指在正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式

LINUX 中常用的有两种正则表达式引擎
基础正则表达式:BRE
扩展正则表达式: ERE

  1. grep [选项]… 查找条件 目标文件

-E :开启扩展(Extend)的正则表达式
-c :计算找到 ‘搜寻字符串’ 的次数
-i :忽略大小写的不同,所以大小写视为相同
-o :只显示被模式匹配到的字符串
-v :反向选择,亦即显示出没有 ‘搜寻字符串’ 内容的那一行!(反向查找,输出与查找条件不相符的行)
–color=auto :可以将找到的关键词部分加上颜色的显示喔!
-n :顺便输出行号

案列
grep -c root /etc/passwd //统计root字符总行数;或cat /etc/passwd | grep root
grep -i “the” web.sh //不区分大小写查找the所有的行
grep -v root /etc/passwd //将/etc/passwd,将没有出现 root 的行取出来
cat web.sh |grep -v ‘^$’ >test.txt //将非空行写入到test.txt文件
ifconfig ens33 |grep -o “[0-9]+.[0-9]+.[0-9]+.[0-9]+”|head -1 //过滤出IP

2.基础正则表达式常见元字符:(支持的工具:grep、egrep、sed、awk)
特殊字符
\:转义符,将特殊字符进行转义,忽略其特殊意义a.b匹配a.b,但不能匹配ajb,.被转义为特殊意义\\
:匹配行首,则是匹配字符串的开始tux匹配以tux开头的行^^^
:匹配行尾, :匹配行尾, :匹配行尾,则是匹配字符串的结尾tux 匹配以 t u x 结尾的行 匹配以tux结尾的行 匹配以tux结尾的行$$$
.:匹配除换行符\r\n之外的任意单个字符
[list]:匹配list列表中的一个字符 例: go[ola]d,[abc]、[a-z]、[a-z0-9]
[^list]:匹配任意不在list列表中的一个字符 例: [a-z]、[0-9]、[^A-Z0-9]
:匹配前面子表达式0次或者多次 例:good、go.*d
{n} :匹配前面的子表达式n次,例:go{2}d、'[O-9]{2}‘匹配两位数字
{n,}:匹配前面的子表达式不少于n次,例: go{2,}d、’ [0-9]{2,}‘匹配两位及两位以上数宁
{n,m}﹔匹配前面的子表达式n到m次,例: go{2,3)d、’[0-9]{2,3}'匹配两位到三位数字
注: egrep、awk使用{n}、{n, }、{n, m}匹配时“{}“前不用加”\”
egrep -E -n ‘wo{2}d’ test.txt //-E 用于显示文件中符合条件的字符
egrep -E -n ‘wo{2,3}d’ test.txt

定位符
^ 匹配输入字符串开始的位置
$ 匹配输入字符串结尾的位置

非打印字符
\n 匹配一个换行符
\r 匹配一个回车符
\t 匹配一个制表符

3.扩展正则表达式(支持的工具:egrep、awk)
通常情况下会使用基础正则表达式就已经足够了,但有时为了简化整个指令,需要使用 范围更广的扩展正则表达式。例如,使用基础正则表达式查询除文件中空白行与行首为“#”

之外的行(通常用于查看生效的配置文件),执行“grep -v‘^KaTeX parse error: Expected group after '^' at position 21: ….txt | grep -v‘^̲#’”即可实现。这里需要使用管…|^#’test.txt”,其中,单引号内的管道符号表示或者(or)。
此外,grep 命令仅支持基础正则表达式,如果使用扩展正则表达式,需要使用 egrep 或 awk 命令。awk 命令在后面的小节进行讲解,这里我们直接使用 egrep 命令。egrep 命令与 grep 命令的用法基本相似。egrep 命令是一个搜索文件获得模式,使用该命令可以搜索文件中的任意字符串和符号,也可以搜索一个或多个文件的字符串,一个提示符可以是单个字符、一个字符串、一个字或一个句子。
与基础正则表达式类型相同,扩展正则表达式也包含多个元字符,常见的扩展正则表达 式的元字符主要包括以下几个.

案列:

  • 作用:重复一个或者一个以上的前一个字符
    示例:执行“egrep -n ‘wo+d’ test.txt”命令,即可查询"wood" “woood” "woooooood"等字符串

? 作用:零个或者一个的前一个字符
示例:执行“egrep -n ‘bes?t’ test.txt”命令,即可查询“bet”“best”这两个字符串

| 作用:使用或者(or)的方式找出多个字符
示例:执行“egrep -n ‘of|is|on’ test.txt”命令即可查询"of"或者"if"或者"on"字符串

() 作用:查找“组”字符串
示例:“egrep -n ‘t(a|e)st’ test.txt”。“tast”与“test”因为这两个单词的“t”与“st”是重复的,所以将“a”与“e”
列于“()”符号当中,并以“|”分隔,即可查询"tast"或者"test"字符串

()+ 作用:辨别多个重复的组
示例:“egrep -n ‘A(xyz)+C’ test.txt”。该命令是查询开头的"A"结尾是"C",中间有一个以上的"xyz"字符串的意思

4.元字符操作的案列

(1)查找特定字符
查找特定字符非常简单,如执行以下命令即可从 test.txt 文件中查找出特定字符“the”所在位置。其中“-n”表示显示行号、“-i”表示不区分大小写。命令执行后,符合匹配标准的字符, 字体颜色会变为红色(本章中全部通过加粗显示代替)。

grep -n ‘the’ test.txt

若反向选择,如查找不包含“the”字符的行,则需要通过 grep 命令的“-v”选项实现,并配合“-n”一起使用显示行号。

grep -vn ‘the’ test.txt

(2)利用中括号“[]”来查找集合字符

想要查找“shirt”与“short”这两个字符串时,可以发现这两个字符串均包含“sh”与“rt”。此时执行以下命令即可同时查找到“shirt”与“short”这两个字符串,其中“[]”中无论有几个字符, 都仅代表一个字符,也就是说“[io]”表示匹配“i”或者“o”。

grep -n ‘sh[io]rt’ test.txt

若要查找包含重复单个字符“oo”时,只需要执行以下命令即可。

grep -n ‘oo’ test.txt

若查找“oo”前面不是“w”的字符串,只需要通过集合字符的反向选择“[^]”来实现该目的。例如执行“grep -n‘[^w]oo’test.txt”命令表示在 test.txt 文本中查找“oo”前面不是“w”的字符串。

grep -n ‘[^w]oo’ test.txt

3:The home of Football on BBC Sport online. 5:google is the best tools for search keyword. 11:#woood #
12:#woooooood #
14:I bet this place is really spooky late at night!

在上述命令的执行结果中发现“woood”与“wooooood”也符合匹配规则,二者均包含“w”。其实通过执行结果就可以看出,符合匹配标准的字符加粗显示,而上述结果中可以得知, “#woood #”中加粗显示的是“ooo”,而“oo”前面的“o”是符合匹配规则的。同理“#woooooood #”也符合匹配规则。
若不希望“oo”前面存在小写字母,可以使用“grep -n‘[^a-z]oo’test.txt”命令实现,其中

“a-z”表示小写字母,大写字母则通过“A-Z”表示。

[root@localhost ~]# grep -n ‘[^a-z]oo’ test.txt
3:The home of Football on BBC Sport online.

查找包含数字的行可以通过“grep -n ‘[0-9]’test.txt”命令来实现。

[root@localhost ~]# grep -n ‘[0-9]’ test.txt
4:the tongue is boneless but it breaks bones.12! 7:PI=3.141592653589793238462643383249901429

(3)查找行首“^”与行尾字符“ ”基础正则表达式包含两个定位元字符: “ ” (行首)与“ ” 基础正则表达式包含两个定位元字符:“^”(行首)与“ 基础正则表达式包含两个定位元字符:(行首)与”(行尾)。在上面的示例中, 查询“the”字符串时出现了很多包含“the”的行,如果想要查询以“the”字符串为行首的行,则可以通过“^”元字符来实现。

[root@localhost ~]# grep -n ‘^the’ test.txt
4:the tongue is boneless but it breaks bones.12!

查询以小写字母开头的行可以通过“1”规则来过滤,查询大写字母开头的行则使用
[A-Z]”规则,若查询不以字母开头的行则使用“[^a-zA-Z]”规则。

[root@localhost ~]# grep -n ‘2’ test.txt
1:he was short and fat.
4:the tongue is boneless but it breaks bones.12! 5:google is the best tools for search keyword.
8:a wood cross!
[root@localhost ~]# grep -n ‘3’ test.txt
2:He was wearing a blue polo shirt with black pants. 3:The home of Football on BBC Sport online.
6:The year ahead will test our political establishment to the limit. 7:PI=3.141592653589793238462643383249901429
9:Actions speak louder than words

13:AxyzxyzxyzxyzC
14:I bet this place is really spooky late at night! 15:Misfortunes never come alone/single.
16:I shouldn’t have lett so tast.
[root@localhost ~]# grep -n ‘[a-zA-Z]’ test.txt
11:#woood # 12:#woooooood #

“^”符号在元字符集合“[]”符号内外的作用是不一样的,在“[]”符号内表示反向选择,在“[]” 符号外则代表定位行首。反之,若想查找以某一特定字符结尾的行则可以使用“$”定位符。例如,执行以下命令即可实现查询以小数点(.)结尾的行。因为小数点(.)在正则表达式中也是一个元字符(后面会讲到),所以在这里需要用转义字符“\”将具有特殊意义的字符转化成普通字符。

[root@localhost ~]# grep -n ‘.$’ test.txt
1:he was short and fat.
2:He was wearing a blue polo shirt with black pants. 3:The home of Football on BBC Sport online.
5:google is the best tools for search keyword.
6:The year ahead will test our political establishment to the limit. 15:Misfortunes never come alone/single.
16:I shouldn’t have lett so tast.

当查询空白行时,执行“grep -n‘^$’test.txt”命令即可。

[root@localhost ~]# grep -n ‘^$’ test.txt
10:

(4)查找任意一个字符“.”与重复字符“*”
前面提到,在正则表达式中小数点(.)也是一个元字符,代表任意一个字符。例如执行以下命令就可以查找“w??d”的字符串,即共有四个字符,以 w 开头 d 结尾。

[root@localhost ~]# grep -n ‘w…d’ test.txt
5:google is the best tools for search keyword.

8:a wood cross!
9:Actions speak louder than words

在上述结果中,“wood”字符串“w…d”匹配规则。若想要查询 oo、ooo、ooooo 等资料, 则需要使用星号()元字符。但需要注意的是,“”代表的是重复零个或多个前面的单字符。 “o*”表示拥有零个(即为空字符)或大于等于一个“o”的字符,因为允许空字符,所以执行“grep
-n ‘o*’ test.txt”命令会将文本中所有的内容都输出打印。如果是“oo*”,则第一个 o 必须存在, 第二个 o 则是零个或多个 o,所以凡是包含 o、oo、ooo、ooo,等的资料都符合标准。同理,若查询包含至少两个 o 以上的字符串,则执行“grep -n ‘ooo*’ test.txt”命令即可。

[root@localhost ~]# grep -n ‘ooo*’ test.txt
3:The home of Football on BBC Sport online. 5:google is the best tools for search keyword. 8:a wood cross!
11:#woood # 12:#woooooood #
14:I bet this place is really spooky late at night!

查询以 w 开头 d 结尾,中间包含至少一个 o 的字符串,执行以下命令即可实现。

[root@localhost ~]# grep -n ‘woo*d’ test.txt
8:a wood cross! 11:#woood # 12:#woooooood #

执行以下命令即可查询以 w 开头 d 结尾,中间的字符可有可无的字符串。

[root@localhost ~]# grep -n ‘w.*d’ test.txt
1:he was short and fat.
5:google is the best tools for search keyword. 8:a wood cross!
9:Actions speak louder than words 11:#woood #
12:#woooooood #

执行以下命令即可查询任意数字所在行。

[root@localhost ~]# grep -n ‘[0-9][0-9]*’ test.txt 4:the tongue is boneless but it breaks bones.12! 7:PI=3.141592653589793238462643383249901429

(5)查找连续字符范围“{}”
在上面的示例中,使用了“.”与“*”来设定零个到无限多个重复的字符,如果想要限制一个范围内的重复的字符串该如何实现呢?例如,查找三到五个 o 的连续字符,这个时候就需要使用基础正则表达式中的限定范围的字符“{}”。因为“{}”在 Shell 中具有特殊意义,所以在使用“{}”字符时,需要利用转义字符“\”,将“{}”字符转换成普通字符。“{}”字符的使用方法如下所示。
① 查询两个 o 的字符。

[root@localhost ~]# grep -n ‘o{2}’ test.txt
3:The home of Football on BBC Sport online.
5:google is the best tools for search keyword.
8:a wood cross!
11:#woood # 12:#woooooood #
14:I bet this place is really spooky late at night!

② 查询以 w 开头以 d 结尾,中间包含 2~5 个 o 的字符串。

[root@localhost ~]# grep -n ‘wo{2,5}d’ test.txt
8:a wood cross! 11:#woood #

③ 查询以 w 开头以 d 结尾,中间包含 2 个或 2 个以上 o 的字符串。

[root@localhost ~]# grep -n ‘wo{2,}d’ test.txt
8:a wood cross!

11:#woood # 12:#woooooood #

总结:元字符
通过上面几个简单的示例,可以了解到常见的基础正则表达式的元字符主要包括以下几个

^ 匹配输入字符串的开始位置。除非在方括号表达式中使用,表示不包含该字符集合。要匹配“^” 字符本身,请使用“^”
$ 匹配输入字符串的结尾位置。如果设置了RegExp 对象的 Multiline 属性,则“KaTeX parse error: Undefined control sequence: \n at position 6: ”也匹配‘\̲n̲’或‘\r’。要匹配“”字符本身,请使用“$”
. 匹配除“\r\n”之外的任何单个字符

\ 反斜杠,又叫转义字符,去除其后紧跟的元字符或通配符的特殊意义

  • 匹配前面的子表达式零次或多次。要匹配“*”字符,请使用“*”

[] 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”

[^] 赋值字符集合。匹配未包含的一个任意字符。例如,“[^abc]”可以匹配“plin”中任何一个字母

[n1-n2] 字符范围。匹配指定范围内的任意一个字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意一个小写字母字符。
注意:只有连字符(-)在字符组内部,并且出现在两个字符之间时,才能表示字符的范围;如果出现在字符组的开头,则只能表示连字符本身

{n} n 是一个非负整数,匹配确定的 n 次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的“oo”
{n,} n 是一个非负整数,至少匹配 n 次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”
{n,m} m 和 n 均为非负整数,其中 n<=m,最少匹配 n 次且最多匹配m 次

cut、sort、uniq、tr

cut:列截取工具

使用说明:

cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。

如果不指定 File 参数,cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一

选项:
-b:按字节截取
-c:按字符截取,常用于中文
-d:指定以什么为分隔符截取,默认为制表符
-f:通常和-d一起

[root@localhost ~]# cat /etc/passwd | cut -d’:’ -f 1
root
bin
daemon

[root@localhost ~]# cat /etc/passwd | cut -d’:’ -f 3
0
1
2

[root@localhost ~]# cat /etc/passwd | cut -d’:’ -f1,3
root:0
bin:1
daemon:2

[root@localhost ~]# cat /etc/passwd | cut -d':' -f1-3
root:x:0
bin:x:1
daemon:x:2

[root@localhost ~]# who | cut -b 3
o
o
o
[root@localhost ~]# who | cut -c 3
o
o
o

[root@localhost ~]# cat name | cut -b 2

[root@localhost ~]# cat name | cut -c 2

注意:cut只擅长于处理单个字符为间隔的文本

sort 排序

是一个以行为单位对文件内容进行排序的工具,也可以根据不同的数据类型来排序。例如数据和字符的排序就不一样
语法:
sort [选项] 参数

常用选项
-t:指定分隔符,默认使用[Tab]吧 键或空格分隔
-k:指定排序区域,哪个区间排序
-n:按照数字进行排序,默认是以文字形式排序
-u:等同于 uniq,表示相同的数据仅显示一行,注意:如果行尾有空格去重就不成功
-r:反向排序,默认是升序,-r就是降序
-o:将排序后的结果转存至指定文件

sort passwd.txt //不加任何选项默认按第一列升序,字母的话就是从a到z由上

sort -n -t: -k3 passwd.txt //以冒号为分隔符,以数字大小对第三列排序(升序)

sort -nr -t: -k3 passwd.txt //以冒号为分隔符,以数字大小对第三列排序(降序)

sort -nr -t: -k3 passwd.txt -o passwd.bak //将输结果不在屏幕上输出而是输出到passwd.bak文件

sort -u passwd.txt //去掉文件中重复的行(重复的行可以是不连续的)
zhangsan
zhangsan
zhangsan
gggggg
lisi

uniq

主要用于去除连续的重复行
注意:是连续的行,所以通常和sort结合使用先排序使之变成连续的行再执行去重操作,否则不连续的重复行他不能去重

(1)语法
uniq [选项] 参数

(2)常用选项
-c:对重复的行进行计数;
-d:仅显示重复行;
-u:仅显示出现一次的行

[root@localhost ~]# cat fruit //创建一个水果类型的文件,一共9行内容
apple
apple
peache
pear
banana
cherry
cherry
banana
orange

[root@localhost ~]# cat fruit | uniq -c //统计重复行的次数,不连续的重复行他不算做重复行
2 apple
1 peache
1 pear
1 banana
2 cherry
1 banana
1 orange

[root@localhost ~]# cat fruit | sort | uniq -c //结合sort使用就是我们想要的效果
2 apple
2 banana
2 cherry
1 orange
1 peache
1 pear

[root@localhost ~]# cat fruit | sort | uniq -d //结合sort使用,过滤出重复行
apple
banana
cherry

[root@localhost ~]# cat fruit | sort | uniq -u //结合sort使用,过滤出不重复的行
orange
peache
pear

[root@localhost ~]# cat fruit | sort | uniq //结合sort使用,去重
apple
banana
cherry
orange
peache
pear

[root@localhost ~]# cat fruit | sort -u //也可以直接用sort -u
apple
banana
cherry
orange
peache
pear

实例1:查看登陆用户
[root@localhost ~]# who
root :0 2021-04-29 00:09 (:0)
root pts/0 2021-04-29 00:09 (:0)
root pts/1 2021-06-10 01:32 (192.168.245.1)
[root@localhost ~]# who | awk ‘{print $1}’
root
root
root
[root@localhost ~]# who | awk ‘{print $1}’| uniq
root

实例2:查看登陆过系统的用户
[root@localhost ~]# last | awk '{print KaTeX parse error: Expected 'EOF', got '}' at position 2: 1}̲' | sort | uniq…" | grep -v wtmp
reboot
root
shengjie

tr替换

它可以用一个字符来替换另一个字符,或者可以完全除去一些字符,也可以用它来除去重复字符

语法
用法:tr [选项]… SET1 [SET2]
从标准输入中替换、缩减和/或删除字符,并将结果写到标准输出。

常用选项
-d 删除字符
-s 删除所有重复出现的字符,只保留第一个

[root@localhost ~]# cat fruit | tr ‘a-z’ ‘A-Z’
APPLE
APPLE
PEACHE
PEAR
BANANA
CHERRY
CHERRY
BANANA
ORANGE

[root@localhost ~]# cat fruit | tr ‘apple’ ‘APPLE’ //替换是一一对应的字母的替换
APPLE
APPLE
PEAchE
PEAr
bAnAnA
chErry
chErry
bAnAnA
orAngE

[root@localhost ~]# cat fruit | tr ‘a’ ’ ’ //把替换的字符用单引号引起来,包括特殊字符
pple
pple
pe che
pe r
b n n
cherry
cherry
b n n
or nge

[root@localhost ~]# cat fruit | tr ‘a’ ‘/’
/pple
/pple
pe/che
pe/r
b/n/n/
cherry
cherry
b/n/n/
or/nge

[root@localhost ~]# cat fruit | tr ‘ap’ ‘/’ //多个字符替换成一个
///le
///le
/e/che
/e/r
b/n/n/
cherry
cherry
b/n/n/
or/nge

[root@localhost ~]# cat fruit | tr ‘apple’ ‘star’ //a替换成s,p替换成a,le替换成r
saarr
saarr
arschr
arsr
bsnsns
chrrry
chrrry
bsnsns
‘orsngr’

[root@localhost ~]# cat fruit | tr “'” ‘/’ //如果想替换单引号则需要用双引号把单引号引起来,反斜杠转义也不行
apple
apple
peache
pear
banana
cherry
cherry
banana
/orange/

[root@localhost ~]# cat fruit | tr -d ‘a’ //删除所有a
pple
pple
peche
per
bnn
cherry
cherry
bnn
‘ornge’

[root@localhost ~]# cat fruit | tr -d ‘apple’ //把所有含有这5个字母的都删除

ch
r
bnn
chrry
chrry
bnn
‘orng’

[root@localhost ~]# cat fruit | tr -d ‘\n’ //删除换行符
appleapplepeachepearbananacherrycherrybanana’orange’[root@localhost ~]#

[root@localhost ~]# cat fruit | tr -s ‘p’ //对p字符去重,只保留第一个
aple
aple
peache
pear
banana
cherry
cherry
banana
‘orange’

[root@localhost ~]# cat fruit | tr -s ‘\n’ //遇到多个回车只保留一个回车,相当于去除空行
apple
apple
peache
pear
banana
cherry
cherry
banana
‘orange’

面试组合使用

1.统计当前连接主机数
ss -nt |tr -s " "|cut -d " " -f5|cut -d “:” -f1 |sort|uniq -c|

2.统计当前主机的连接状态
ss -nta | grep -v ‘^State’ |cut -d" " -f1|sort |uniq -c

sed

sed(Stream EDitor)是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本内容进行编辑(删除、替换、添加、移动等),最后输出所有行或者仅输出处理的某些行。sed也可以在无交互的情况下实现相当复杂的文本处理操作,被广泛应用于Shell脚本中,用以完成各种自动化处理任务。
sed 的工作流程主要包括读取、执行和显示三个过程。
读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。
执行:默认情况下,所有的 sed 命令都在模式空间中顺序地执行,除非指定了行的地址,否则 sed 命令将会在所有的行上依次执行。
显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。

注意:默认情况下所有的 sed 命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。

1.sed 命令常见用法

通常情况下调用 sed 命令有两种格式,如下所示。其中,“参数”是指操作的目标文件, 当存在多个操作对象时用,文件之间用逗号“,”分隔;而 scriptfile 表示脚本文件,需要用“-f” 选项指定,当脚本文件出现在目标文件之前时,表示通过指定的脚本文件来处理输入的目标文件。

sed [选项] ‘操作’ 参数
sed [选项] -f scriptfile 参数

常见的 sed 命令选项主要包含以下几种。
-e 或–expression=:表示用指定命令或者脚本来处理输入的文本文件。
-f 或–file=:表示用指定的脚本文件来处理输入的文本文件。
-h 或–help:显示帮助。
-n、–quiet 或 silent:表示仅显示处理后的结果。
-i.bak:直接编辑文本文件。
-r, -E 使用扩展正则表达式
-s 将多个文件视为独立文件,而不是单个连续的长文件流

“操作”用于指定对文件操作的动作行为,也就是 sed 的命令。通常情况下是采用的“[n1[,n2]]”操作参数的格式。n1、n2 是可选的,代表选择进行操作的行数,如操作需要在 5~ 20 行之间进行,则表示为“5,20 动作行为”。常见的操作包括以下几种。
a:增加,在当前行下面增加一行指定内容。
c:替换,将选定行替换为指定内容。
d:删除,删除选定的行。
i:插入,在选定行上面插入一行指定内容。
p:打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以 ASCII 码输出。其通常与“-n”选项一起使用。
s:替换,替换指定字符。
y:字符转换。

2.用法示例

在本小节中依旧以 test.txt 文件为例进行演示。

(1)输出符合条件的文本(p 表示正常输出)

sed -n ‘p’ test.txt

//输出所有内容,等同于 cat test.txt

[root@localhost ~]# sed -n ‘3p’ test.txt //输出第 3 行
[root@localhost ~]# sed -n ‘3,5p’ test.txt //输出 3~5 行
[root@localhost ~]# sed -n ‘p;n’ test.txt //输出所有奇数行,n 表示读入下一行资料
[root@localhost ~]# sed -n ‘n;p’ test.txt //输出所有偶数行,n 表示读入下一行资料
[root@localhost ~]# sed -n ‘1,5{p;n}’ test.txt //输出第 1~5 行之间的奇数行(第 1、3、5 行) he was short and fat.
[root@localhost ~]# sed -n ‘10,${n;p}’ test.txt //输出第 10 行至文件尾之间的偶数行
#woood # AxyzxyzxyzxyzC
Misfortunes never come alone/single.

案列
ifconfig ens33|sed -n 2p #直接显示第二行内容

在执行“sed -n‘10,${n;p}’test.txt”命令时,读取的第 1 行是文件的第 10 行,读取的第 2
行是文件的第 11 行,依此类推,所以输出的偶数行是文件的第 11 行、13 行直至文件结尾, 其中包括空行。

以上是 sed 命令的基本用法,sed 命令结合正则表达式时,格式略有不同,正则表达式以“/”包围。例如,以下操作是 sed 命令与正则表达式结合使用的示例。

[root@localhost ~]# sed -n ‘/the/p’ test.txt //输出包含the 的行
the tongue is boneless but it breaks bones.12! google is the best tools for search keyword.
The year ahead will test our political establishment to the limit.
[root@localhost ~]# sed -n ‘4,/the/p’ test.txt //输出从第 4 行至第一个包含 the 的行
the tongue is boneless but it breaks bones.12! google is the best tools for search keyword.
[root@localhost ~]# sed -n ‘/the/=’ test.txt
//输出包含the 的行所在的行号,等号(=)用来输出行号
4
5
6
[root@localhost ~]# sed -n ‘/^PI/p’ test.txt //输出以PI 开头的行
PI=3.141592653589793238462643383249901429
[root@localhost ~]# sed -n ‘/[0-9]$/p’ test.txt //输出以数字结尾的行PI=3.141592653589793238462643383249901429
[root@localhost ~]# sed -n ‘//p’ test.txt //输出包含单词wood 的行,<、>代表单词边界
a wood cross!

(2)删除符合条件的文本(d)

因为后面的示例还需要使用测试文件 test.txt,所以在执行删除操作之前需要先将测试文件备份。以下示例分别演示了 sed 命令的几种常用删除用法。
下面命令中 nl 命令用于计算文件的行数,结合该命令可以更加直观地查看到命令执行的结果。

[root@localhost ~]# nl test.txt | sed ‘3d’ //删除第 3 行
1he was short and fat.
2He was wearing a blue polo shirt with black pants.
4the tongue is boneless but it breaks bones.12!
5google is the best tools for search keyword.
6The year ahead will test our political establishment to the limit.
…… //省略部分内容
[root@localhost ~]# nl test.txt | sed ‘3,5d’ //删除第 3~5 行
1he was short and fat.
2He was wearing a blue polo shirt with black pants.
6 The year ahead will test our political establishment to the limit. 7 PI=3.141592653589793238462643383249901429
8a wood cross!
…… //省略部分内容
[root@localhost ~]# nl test.txt |sed ‘/cross/d’
//删除包含 cross 的行,原本的第 8 行被删除;如果要删除不包含 cross 的行,用!符号表示取反操作, 如’/cross/!d’
…… //省略部分内容
7 PI=3.141592653589793238462643383249901429
9Actions speak louder than words
…… //省略部分内容
[root@localhost ~]# sed ‘/4/d’ test.txt //删除以小写字母开头的行He was wearing a blue polo shirt with black pants.
The home of Football on BBC Sport online.
The year ahead will test our political establishment to the limit. PI=3.141592653589793238462643383249901429
Actions speak louder than words

#woood # #woooooood # AxyzxyzxyzxyzC
I bet this place is really spooky late at night! Misfortunes never come alone/single.
I shouldn’t have lett so tast.

[root@localhost ~]# sed ‘/.$/d’ test.txt //删除以"."结尾的行the tongue is boneless but it breaks bones.12!
PI=3.141592653589793238462643383249901429
a wood cross!
Actions speak louder than words

#woood # #woooooood # AxyzxyzxyzxyzC
I bet this place is really spooky late at night!

[root@localhost ~]# sed ‘/^$/d’ test.txt //删除所有空行he was short and fat.
He was wearing a blue polo shirt with black pants. The home of Football on BBC Sport online.
the tongue is boneless but it breaks bones.12! google is the best tools for search keyword.
The year ahead will test our political establishment to the limit.
PI=3.141592653589793238462643383249901429
a wood cross!
Actions speak louder than words #woood #
#woooooood # AxyzxyzxyzxyzC
I bet this place is really spooky late at night! Misfortunes never come alone/single.
I shouldn’t have lett so tast.

注 意 : 若 是 删 除 重 复 的 空行 , 即 连 续 的 空 行 只 保 留 一 个 , “cat -s test.txt”。

(3)替换符合条件的文本

在使用 sed 命令进行替换操作时需要用到 s(字符串替换)、c(整行/整块替换)、y
(字符转换)命令选项,常见的用法如下所示。

sed ‘s/the/THE/’ test.txt //将每行中的第一个the 替换为 THE
sed ‘s/l/L/2’ test.txt //将每行中的第 2 个 l 替换为 L
sed ‘s/the/THE/g’ test.txt //将文件中的所有the 替换为 THE

sed ‘s/o//g’ test.txt //将文件中的所有o 删除(替换为空串)
sed ‘s/^/#/’ test.txt //在每行行首插入#号
sed ‘/the/s/^/#/’ test.txt //在包含the 的每行行首插入#号
sed ‘s/$/EOF/’ test.txt //在每行行尾插入字符串EOF
sed ‘3,5s/the/THE/g’ test.txt //将第 3~5 行中的所有 the 替换为 THE
sed ‘/the/s/o/O/g’ test.txt //将包含the 的所有行中的 o 都替换为 O

sed -i.bak ‘s/SELINUX=disabled/SELINUX=enable/’ /etc/selinux/config

(4)迁移符合条件的文本

在使用 sed 命令迁移符合条件的文本时,常用到以下参数.
H:复制到剪贴板;
g、G:将剪贴板中的数据覆盖/追加至指定行;
w:保存为文件;
r:读取指定文件;
a:追加指定内容。具体操作方法如下所示。
I,i 忽略大小写

sed ‘/the/{H;d};$G’ test.txt //将包含the 的行迁移至文件末尾,{;}用于多个操作
sed ‘1,5{H;d};17G’ test.txt //将第 1~5 行内容转移至第 17 行后
sed ‘/the/w out.file’ test.txt //将包含the 的行另存为文件 out.file
sed ‘/the/r /etc/hostname’ test.txt //将文件/etc/hostname 的内容添加到包含 the 的每行以后
sed ‘3aNew’ test.txt //在第 3 行后插入一个新行,内容为New
sed ‘/the/aNew’ test.txt //在包含the 的每行后插入一个新行,内容为 New
sed ‘3aNew1\nNew2’ test.txt //在第 3 行后插入多行内容,中间的\n 表示换行

(5)使用脚本编辑文件

使用 sed 脚本将多个编辑指令存放到文件中(每行一条编辑指令),通过“-f”选项来调用。例如执行以下命令即可将第 1~5 行内容转移至第 16 行后。

sed ‘1,5{H;d};16G’ test.txt //将第 1~5 行内容转移至第 16 行后

以上操作可以改用脚本文件方式:

[root@localhost ~]# vi opt.list
1,5H
1,5d
16G
[root@localhost ~]# sed -f opt.list test.txt
The year ahead will test our political establishment to the limit.
PI=3.141592653589793238462643383249901429
a wood cross!
Actions speak louder than words

#woood # #woooooood # AxyzxyzxyzxyzC
I bet this place is really spooky late at night! Misfortunes never come alone/single.
I shouldn’t have lett so tast.

he was short and fat.
He was wearing a blue polo shirt with black pants. The home of Football on BBC Sport online.
the tongue is boneless but it breaks bones.12! google is the best tools for search keyword.

|| 表示上一条命令执行失败后,才执行下一条命令

扩展或作业

(6)sed 直接操作文件示例

编写一个脚本,用来调整 vsftpd 服务配置,要求禁止匿名用户,但允许本地用户(也允许写入)。

[root@lo calhost ~]# vim local_only_ftp.sh
#!/bin/bash

指定样本文件路径、配置文件路径

SAMPLE=“/usr/share/doc/vsftpd-3.0.2/EXAMPLE/INTERNET_SITE/vsftpd.conf "
CONFIG=”/etc/vsftpd/vsftpd.conf"

备份原来的配置文件,检测文件名为/etc/vsftpd/vsftpd.conf.bak 备份文件是否存在, 若不存在则使用 cp 命令进行文件备份

[ ! -e “$CONFIG.bak” ] && cp $CONFIG $CONFIG.bak # 基于样本配置进行调整,覆盖现有文件
sed -e ‘/^anonymous_enable/s/YES/NO/g’ $SAMPLE > $CONFIG

sed -i -e ‘/^local_enable/s/NO/YES/g’ -e ‘/^write_enable/s/NO/YES/g’ $CONFIG
grep “listen” C O N F I G ∣ ∣ s e d − i ′ CONFIG || sed -i ' CONFIG∣∣sedialisten=YES’ $CONFIG

启动vsftpd 服务,并设为开机后自动运行

systemctl restart vsftpd systemctl enable vsftpd
[root@localhost ~]# chmod +x local_only_ftp.sh

分组操作
当我们需要对一行数据进行多次操作的时候我们可以使用{}进行分组

1) sed ‘/root/{s/root/ROOT/;s/x/X/g}’ /tmp/passwd

2) sed -ne ‘/root/{s/root/ROOT/;s/x/X/g}’ -ne ‘1,10p’ /tmp/passwd

3)echo 123abcxyz |sed -r ‘s/(123)(abc)(xyz)/\1/’ ###分组 s//代表查找替换 ()代表分组 \1 代表留下的组

4)ifconfig ens33|sed -rn ‘2s/.inet ([0-9.]+) ./\1/p’

5)sed -r s/5*/#/ /etc/hosts.bak

grep

语法:
grep[options] [pattern] file
命令 参数 匹配模式 文件数据

-a --text  # 不要忽略二进制数据。
-A <显示行数>   --after-context=<显示行数>   # 除了显示符合范本样式的那一行之外,并显示该行之后的内容。
-b --byte-offset                           # 在显示符合范本样式的那一行之外,并显示该行之前的内容。
-B<显示行数>   --before-context=<显示行数>   # 除了显示符合样式的那一行之外,并显示该行之前的内容。
-c --count    # 计算符合范本样式的列数。
-C<显示行数> --context=<显示行数>或-<显示行数> # 除了显示符合范本样式的那一列之外,并显示该列之前后的内容。
-d<进行动作> --directories=<动作>  # 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep命令将回报信息并停止动作。
-e<范本样式> --regexp=<范本样式>   # 指定字符串作为查找文件内容的范本样式。
-E --extended-regexp             # 将范本样式为延伸的普通表示法来使用,意味着使用能使用扩展正则表达式。
-f<范本文件> --file=<规则文件>     # 指定范本文件,其内容有一个或多个范本样式,让grep查找符合范本条件的文件内容,格式为每一列的范本样式。
-F --fixed-regexp   # 将范本样式视为固定字符串的列表。
-G --basic-regexp   # 将范本样式视为普通的表示法来使用。
-h --no-filename    # 在显示符合范本样式的那一列之前,不标示该列所属的文件名称。
-H --with-filename  # 在显示符合范本样式的那一列之前,标示该列的文件名称。
-i --ignore-case    # 忽略字符大小写的差别。
-l --file-with-matches   # 列出文件内容符合指定的范本样式的文件名称。
-L --files-without-match # 列出文件内容不符合指定的范本样式的文件名称。
-n --line-number         # 在显示符合范本样式的那一列之前,标示出该列的编号。
-q --quiet或--silent     # 不显示任何信息。
-R/-r  --recursive       # 此参数的效果和指定“-d recurse”参数相同。
-s --no-messages  # 不显示错误信息。
-v --revert-match # 反转查找。
-V --version      # 显示版本信息。   
-w --word-regexp  # 只显示全字符合的列。
-x --line-regexp  # 只显示全列符合的列。
-y # 此参数效果跟“-i”相同。
-o # 只输出文件中匹配到的部分。

awk

概述:
AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。
它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作
数据可以来自标准输入也可以是管道或文件
20世纪70年代诞生于贝尔实验室,现在centos7用的是gawk

之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

工作原理:
当读到第一行时,匹配条件,然后执行指定动作,再接着读取第二行数据处理,不会默认输出
如果没有定义匹配条件默认是匹配所有数据行,awk隐含循环,条件匹配多少次动作就会执行多少次

工作原理:
逐行读取文本,默认以空格或tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。
sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个"“字段"然后再进行处理。awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。在使用awk命令的过程中,可以使用逻辑操作符” &&“表示"与”、“||表示"或”、"!“表示非”;还可以进行简单的数学运算,如+、一、*、/、%、^分别表示加、减、乘、除、取余和乘方。

命令格式:

awk选项’模式或条件{操作}'文件1文件2 …
awk -f 脚本文件 文件1 文件2 …

格式:awk关键字 选项 命令部分 ‘{xxxx}’ 文件名

awk 包含几个特殊的内建变量(可直接用)如下所示:
FS:指定每行文本的字段分隔符,默认为空格或制表位。
NF:当前处理的行的字段个数。
NR:当前处理的行的行号(序数)。
$0:当前处理的行的整行内容。
$n:当前处理行的第 n 个字段(第 n 列)。
FILENAME:被处理的文件名。

RS:行分隔符。awk从文件上读取资料时,将根据Rs的定义把资料切割成许多条记录, 而awk一次仅读入一条记录,以进行处理。预设值是" \n’
简说:数据记录分隔,默认为\n,即每行为一条记录

[root@localhost ~]# cat /etc/passwd | head -10 > zz  
[root@localhost ~]# awk '{print}' zz    
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@localhost ~]# awk '{print $1}' zz
root:x:0:0:root:/root:/bin/bash    //awk默认把这一行当做一列,因为没有被空格分隔,awk默认以空格或tab键分隔
bin:x:1:1:bin:/bin:/sbin/nologin
hello
[root@localhost ~]# awk -F: '{print $5}' zz   //自定义冒号为分隔符显示分隔之后的第五列
root
bin
[root@localhost ~]# awk -Fx '{print $1}' /etc/passwd   //用x作为分隔符
root:
[root@localhost ~]# awk '{print $1 $2}' zz
helloworld

[root@localhost ~]# awk ‘{print $1""$2}’ zz //显示一个空格,空格需要用双引号引起来,如果不用引号默认以变量看待,如果是常量就需要双引号引起来
hello world

[root@localhost ~]# awk ‘{print $1,$2}’ zz //逗号有空格效果
hello world

[root@localhost ~]# awk -F: ‘{print $1"\t"$2}’ /etc/passwd //用制表符作为分隔符输出

[root@localhost ~]# awk -F[] ‘{print $9}’ zz //定义多个分隔符,只要看到其中一个都算作分隔符
bin
sbin

awk常用内置变量:$1、$2、NF、NR、$0
$1:代表第一列
$2:代表第二列以此类推
$0:代表整行
NF:一行的列数
NR:行数

[root@localhost ~]# awk -F: '/root/{print $0}' pass.txt    //打印包含root的整行内容
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# awk -F: '/root/{print $1}' pass.txt      //打印包含root的行的第一列
root
[root@localhost ~]# awk -F: '/root/{print $1,$6}' pass.txt    //打印包含root的行的第一列和第六列
root /root
[root@localhost ~]# awk '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

输出shadow文件中以冒号分隔的第二列有感叹号的行的第一列

[root@localhost ~]# awk -F[] ‘{print NF}’ zz //打印每一行的列数
10
10

[root@localhost ~]# awk -F[] ‘{print NR}’ zz //显示行号
1
2

[root@localhost ~]# awk -F: ‘{print NR}’ pass.txt
1
2
3
4
5

[root@localhost ~]# awk -F: '{print NR,$0}' pass.txt 
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost ~]# awk  'NR==2' /etc/passwd   //打印第二行,不加print也一样,默认就是打印
bin:x:1:1:bin:/bin:/sbin/nologin
[root@localhost ~]# awk  'NR==2{print}' /etc/passwd    //同上效果 
bin:x:1:1:bin:/bin:/sbin/nologin

[root@localhost ~]# awk -F: ‘NR==2{print $1}’ /etc/passwd //打印第二行的第一列

[root@localhost ~]# awk -F: ‘{print $NF}’ /etc/passwd //打印最后一列
/bin/bash
/sbin/nologin

[root@localhost ~]# awk ‘END{print NR}’ /etc/passwd //打印总行数
65

[root@localhost ~]# awk 'END{print $0}' /etc/passwd    //打印文件最后一行
stu10:x:1020:1020::/home/stu10:/bin/bash

[root@localhost ~]# awk -F: ‘{print “当前行有"NF"列”}’ zz
当前行有7列
当前行有7列

[root@localhost ~]# awk -F: ‘{print “第"NR"行有"NF"列”}’ /etc/passwd //第几行有几列
第1行有7列
第2行有7列
第3行有7列

扩展生产:网卡的ip、流量
[root@localhost ~]# ifconfig ens33 | awk ‘/netmask/{print “本机的ip地址是”$2}’
本机的ip地址是192.168.245.211

[root@localhost ~]# ifconfig ens33 | awk ‘/RX p/{print $5"字节"}’
8341053字节

根分区的可用量
[root@localhost ~]# df -h | awk ‘NR==2{print $4}’
45G

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7uO1Zshw-1658059399874)(C:\Users\10095\AppData\Roaming\Typora\typora-user-images\image-20220708104657618.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9bcN4BEq-1658059399875)(C:\Users\10095\AppData\Roaming\Typora\typora-user-images\image-20220708104729303.png)]

逐行执行开始之前执行什么任务,结束之后再执行什么任务,用BEGIN、END
BEGIN一般用来做初始化操作,仅在读取数据记录之前执行一次
END一般用来做汇总操作,仅在读取完数据记录之后执行一次

awk的运算:
[root@localhost ~]# awk ‘BEGIN{x=10;print x}’ //如果不用引号awk就当作一个变量来输出了,所以不需要加$了
10
[root@localhost ~]# awk ‘BEGIN{x=10;print x+1}’ //BEGIN在处理文件之前,所以后面不跟文件名也不影响
11
[root@localhost ~]# awk ‘BEGIN{x=10;x++;print x}’
11
[root@localhost ~]# awk ‘BEGIN{print x+1}’ //不指定初始值,初始值就为0,如果是字符串,则默认为空
1
[root@localhost ~]# awk ‘BEGIN{print 2.5+3.5}’ //小数也可以运算
6
[root@localhost ~]# awk ‘BEGIN{print 2-1}’
1
[root@localhost ~]# awk ‘BEGIN{print 3*4}’
12
[root@localhost ~]# awk 'BEGIN{print 32}’
9
[root@localhost ~]# awk ‘BEGIN{print 2^3}’ //^和
都是幂运算
8

[root@localhost ~]# awk ‘BEGIN{print 1/2}’
0.5

[root@localhost ~]# awk -F: '/root/' /etc/passwd      //如果后面有具体打印多少列就没法省略print了
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
模糊匹配,用表示包含,!表示不包含
[root@localhost ~]# awk -F: '$1~/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# awk -F: '$1~/ro/' /etc/passwd   //模糊匹配,只要有ro就匹配上
root:x:0:0:root:/root:/bin/bash
chrony:x:993:988::/var/lib/chrony:/sbin/nologin
setroubleshoot:x:990:984::/var/lib/setroubleshoot:/sbin/nologin

[root@localhost ~]# awk -F: ‘ 7 !   / n o l o g i n 7!~/nologin 7! /nologin/{print $1,$7}’ /etc/passwd

关于数值与字符串的比较
比较符号:== != <= >= < >

[root@localhost ~]# awk  'NR==5{print}' /etc/passwd
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost ~]# awk  'NR==5' /etc/passwd
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost ~]# awk  'NR<5' /etc/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@localhost ~]# awk -F: '$3==0' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# awk -F: '$1==root' /etc/passwd
[root@localhost ~]# awk -F: '$1=="root"' /etc/passwd    //精确匹配一定是root
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# awk -F: '$3>=1000' /etc/passwd
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
shengjie:x:1000:1000:shengjie:/home/shengjie:/bin/bash
逻辑运算 && ||

[root@localhost ~]# awk -F: ‘$3<10 || $3>=1000’ /etc/passwd
[root@localhost ~]# awk -F: ‘$3>10 && $3<1000’ /etc/passwd

[root@localhost ~]# awk -F: ‘NR>4 && NR<10’ /etc/passwd

案列:
打印1-200之间所有能被7整除并且包含数字7的整数数字
[root@localhost ~]# seq 200 | awk ‘$1%7==0 && $1~/7/’
7
70
77
147
175

其他内置变量的用法FS、OFS、NR、FNR、RS、ORS

[root@localhost ~]# awk ‘BEGIN{FS=“:”}{print $1}’ pass.txt //在打印之前定义字段分隔符为冒号
root
bin
daemon
adm
lp

[root@localhost ~]# awk ‘BEGIN{FS=“:”;OFS=“—”}{print $1,$2}’ pass.txt //OFS定义了输出时以什么分隔,$1$2中间要用逗号分隔,因为逗号默认被映射为OFS变量,而这个变量默认是空格
root—x
bin—x
daemon—x
adm—x
lp—x

[root@localhost ~]# awk ‘{print FNR,$0}’ /etc/resolv.conf /etc/hosts //可以看出FNR的行号在追加当有多个文件时
1
2 nameserver 114.114.114.114
3 search localdomain
1 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
2 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
[root@localhost ~]# awk ‘{print NR,$0}’ /etc/resolv.conf /etc/hosts
1
2 nameserver 114.114.114.114
3 search localdomain
4 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
5 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

[root@localhost ~]# awk ‘BEGIN{RS=“:”}{print $0}’ /etc/passwd //RS:指定以什么为换行符,这里指定是冒号,你指定的肯定是原文里存在的字符
root
x
0
0
root

[root@localhost ~]# awk ‘BEGIN{ORS=" "}{print $0}’ /etc/passwd //把多行合并成一行输出,输出的时候自定义以空格分隔每行,本来默认的是回车键

awk高级用法
定义引用变量

[root@localhost ~]# a=100
[root@localhost ~]# awk -v b=“KaTeX parse error: Expected 'EOF', got '#' at position 76: …ot@localhost ~]#̲ awk 'BEGIN{pri…a’”}’ //直接调用的话需要先用双引号再用单引号
100

[root@localhost ~]# awk -vc=1 ‘BEGIN{print c}’ //awk直接定义变量并引用
1

调用函数getline,读取一行数据的时候并不是得到当前行而是当前行的下一行
[root@localhost ~]# df -h | awk ‘BEGIN{getline}/root/{print $0}’
/dev/mapper/centos-root 50G 5.2G 45G 11% /

[root@localhost ~]# seq 10 | awk ‘{getline;print $0}’ //显示偶数行
2
4
6
8
10
[root@localhost ~]# seq 10 | awk ‘{print $0;getline}’ //显示奇数行
1
3
5
7
9

if语句:awk的if语句也分为单分支、双分支和多分支

单分支为if(){}
双分支为if(){}else{}
多分支为if(){}else if(){}else{}

[root@localhost ~]# awk -F: ‘{if($3<10){print $0}}’ /etc/passwd //第三列小于10的打印整行
[root@localhost ~]# awk -F: ‘{if($3<10){print $3}else{print $1}}’ /etc/passwd //第三列小于10的打印第三列,否则打印第一列

awk还支持for循环、while循环、函数、数组等

其他

awk 'BEGIN{x=0};//bin/bash$/ {x++;print x,KaTeX parse error: Expected 'EOF', got '}' at position 2: 0}̲;END {print x}'…" /etc/passwd
BEGIN模式表示,在处理指定的文本之前,需要先执行BEGIN模式中指定的动作; awk再处理指定的文本,之后再执行END模式中指定的动作,END{}语句块中,往往会放入打印结果等语句

awk -F “:” '! ($3<200){print} ’ /etc/passwd#输出第3个字段的值不小于200的行
awk ‘BEGIN {FS=“:”} ;{if($3>=1000){print}}’ /etc/passwd #先处理完BEGIN的内容,再打印文本里面的内容

awk -F “:” ’ {max=($3>=$4) ?$3:$4; {print max}} ’ /etc/passwd (了解)
#($3>$4)?$3:$4三元运算符,如果第3个字段的值大于等于第4个字段的值,则把第3个字段的值赋给max,否则第4个字段的值赋给max

awk -F “:” ‘{print NR,$0}’ /etc/passwd #输出每行内容和行号,每处理完一条记录,NR值加1
sed -n ‘=;p’ /etc/passwd

awk -F “:” ‘$7~“bash”{print $1,47}’ /etc/passwd#输出以冒号分隔且第7个字段中包含/bash的行的第1个字段
awk -F: ‘/bash/ {print $1}’ /etc/passwd

awk -F":"'($1~“root”) && (NF==7) {print $1, 2 , 2, 2,NF } ’ /etc/passwd
第1个字段中包含root且有7个字段的行的第1、2个字段

awk -F “:”‘($7!=“/bin/bash”)&&(KaTeX parse error: Expected 'EOF', got '#' at position 82: …in/nologin的所有行 #̲输出第7个字段既不为/bin/…NF !=" /bin/bash")&&($NF !=" /sbin/nologin" ) {print NR, $0}’ passwd

通过管道、双引号调用shell 命令:
echo $PATH | awk ‘BEGIN{RS=“:”};END {print NR}’ #统计以冒号分隔的文本段落数,END{ }语句块中,往往会放入打印结果等语句
echo $PATH | awk ‘BEGIN{RS=“:”};{print NR,$0};END {print NR}’

awk -F: '/bashKaTeX parse error: Expected 'EOF', got '#' at position 35: … /etc/passwd #̲调用wc -l命令统计使用ba…" etc/passwd
awk -F: '/bash$/ {print}'passwd | wc -l

free -m |awk '/Mem:/ {print int($3/($3+$4)100)“%”}’#查看当前内存使用百分比
[ root@localhost ~]# free -m | awk '/Mem:/ {print $3/$2}'0.327869
[root@localhost ~]# free -m | awk /Mem:/ {print $3/$2
100}'32.7869
[ root@localhost ~]# free -m | awk '/Mem:/ {print int$3/$2100}’
[ root@localhost ~]# free -m | awk '/Mem:/ fprint int($3/$2
100)}'32
[ root@localhost ~]# free -m | awk '/Mem:/ {print int($3/$2*100)“%”}’32%

free -m | awk ‘/Mem:/ {print $3/$2*100}’ | awk -F. ‘{print $1 “%”}’

top -b -n 1 | grep Cpu | awk -F ‘,’ ‘{print $4}’| awk ‘{print $1}’ #查看当前CPU空闲率,(-b -n 1表示只需要1次的输出结果)

dao 100%

date -d “$(awk -F “.” ‘{print $1}’/proc/uptime) second ago”+“%F %H:%M:%S”

显示上次系统重启时间,等同于uptime; second ago为显示多少秒前的时间,+$” 选日:3N:3S等同于+"3Y-n-%d 3日:8N:8S"的时间格式

date -d "$(awk -F “.” ‘{iprint $1}’/proc/uptime) second ago”+“号F%H:%M:%S”
#显示上次系统重启时间,等同于uptime; second ago为显示多少秒前的时间,+“F悉日:M::S"等同于+”%1-tm-d 日: 38:8S"的时间格式

awk ‘BEGIN {n=0 ; while (“w” | getline) n++ ; {print n-2}}’#调用w命令,并用来统计在线用户数

awk 'BEGIN { “hostname” | getline ; {print KaTeX parse error: Expected 'EOF', got '}' at position 2: 0}̲}'#调用hostname,并…O等内部变量,所以此时的$O的值就不再是1,而是2了,然后将它打印出来。
当getline左右有重定向符"<"或"I"时,getline则作用于定向输入文件,由于该文件是刚打开,
并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行。

seq 10 | awk ’ {getline; print $0 }’
seq 10 | awk ’ { print $0 ; getline } ’

CPU使用率
cpu_us=top -b -n 1 | grep Cpu | awk '{print $2}'
cpu_sy=top -b -n 1 | grep Cpu | awk -F ',' '{print $2}' | awk '{print $1} '
cpu_sum= ( ( (( ((cpu_us+$cpu_sy))
echo $cpu_sum

echo “A B C D” | awk ‘{OFS=“|”; print $0;$1=$1;print $0}’
A B C D
A/BlC|D
$1=$1是用来激活$0的重新赋值,也就是说
字段 1... 和字段数 N F 的改变会促使 a w k 重新计算 1...和字段数NF的改变会促使awk重新计算 1...和字段数NF的改变会促使awk重新计算O的值,通常是在改变OFS后而需要输出$O时这样做

echo “A B C D” | awk ‘BEGIN{OFS=“|”};{print $0;$1=$1;print $0}’
echo “A B C D” | awk ‘BEGIN{OFS=“|”};{print $0;$1=$1;print $1,$2}’
echo “A B C D” | awk ‘BEGIN{OFS=“|”};{$2=$2;print $1,$2}’

awk ‘BEGIN{a[0]=10;a[1]=20;print a[1]}’
awk ‘BEGIN{a[0]=10;a[1]=20;print a[0]}’
awk ‘BEGIN{a[“abc”]=10;a[“xyz”]=20;print a[“abc”]}’
awk ‘BEGIN{a[“abc”]=10;a[“xyz”]=20;print a[“xyz”]}’
awk ‘BEGIN{a[“abc”]=“aabbcc”;a[“xyz”]=“xxyyzz”;print a[“xyz”]}’
awk ‘BEGIN{a[0]=10;a[1]=20;a[2]=30;for(i in a){print i,a[i]}}’
PS1:BEGIN中的命令只执行一次
PS2: awk数组的下标除了可以使用数字,也可以使用字符串,字符串需要使用双引号

使用awk统计httpd 访问日志中每个客户端IP的出现次数?
答案:
awk ‘{ip[$1]++}END{for(i in ip)(print ip[i],i}’ /var/log/httpd/access_log | sort -r
备注:定义数组,数组名称为ip,数字的下标为日志文件的第1列(也就是客户端的IP地址),++的目的在于对客户端进行统计计数,客户端IP出现一次计数器就加1。END中的指令在读取完文件后执行,通过循环将所有统计信息输出,for循环遍历的是数组名ip的下标。

awk '/Failed password/ {print $0} ’ /var/log/secure
awk '/Failed password/ {print $11} ’ /var/log/secure

awk ‘/Failed/{ip[$11]++}END{for(i in ip){print i","ip[i]}}’ /var/log/secure

awk ‘/Failed/{ip[$11]++}END{for(i in ip){print i","ip[i]}}’ /var/log/secure

zhengqu
awk ‘/Failed password/{ip[$11]++}END{for(i in ip){print i","ip[i]}}’ /var/log/secure

脚本编写
#!/bin/ bash
x=awk '/Failed password/{ip[$11]++}END{for(i in ip){print i","ip[i]}}' /var/log/secure
#190.168.80.13 3
for j in $x
do
ip=echo $j | awk -F "," '{print $1}'
num=echo $j | awk -F "," '{print $2}'
if [ $num -ge 3 ];then
echo “警告! i p 访问本机失败了 ip访问本机失败了 ip访问本机失败了num次,请速速处理!”
fi
done


  1. a-z ↩︎

  2. a-z ↩︎

  3. A-Z ↩︎

  4. a-z ↩︎

  5. \t ↩︎

你可能感兴趣的:(shell,正则表达式)