Shell正则表达式与文本处理三剑客(grep、sed、awk)
一、正则表达式
Shell正则表达式分为两种:
基础正则表达式:BRE(basic regular express)
扩展正则表达式:ERE(extend regular express),扩展的表达式有+、?、|和()
1.1 基本正则表达式

1.2 扩展正则表达式

1.3 支持正则表达式的工具
grep:默认不支持扩展表达式,加-E选项开启ERE。如果不加-E使用花括号要加转义符\{\}
egrep:支持基础和扩展表达式
awk:支持egrep所有的正则表达式
sed:默认不支持扩展表达式,加-r选项开启ERE。如果不加-r使用花括号要加转义符\{\}
二、grep
过滤来自一个文件或标准输入匹配模式内容。

除此之外还有:
grep -f:从文件每一行获取匹配模式
grep -m:输出匹配的结果num数
grep -H:打印每个匹配的文件名
grep -h:不输出文件名
grep -q:不输出正常信息
grep -s:不输出错误信息
grep -r:递归目录
grep -B:打印匹配的前几行
grep -A:打印匹配的后几行
grep -C:打印匹配的前后几行
grep --color:匹配的字体颜色
(1)输出b文件在a文件相同的行
> grep -f a b
(2)输出b文件在a文件不同的行
> grep -v -f a b
(3)匹配多个模式
> echo "a bc de" |xargs -n1 |grep -e 'a' -e 'bc'
a
bc
注:xargs为多行输出,-n1表示一行输出1个参数
(4)去除文件内的空行和#开头的行(一般用于查看配置文件)
> grep -E -v "^$|.*#" /etc/httpd/conf/httpd.conf
(5)匹配开头不分大小写的单词
> echo "A a b c" |xargs -n1 |grep -i a
A
a
(6)只显示匹配的字符串
> echo "this is a test" |grep -o 'is'
is
is
(7)输出匹配的前五个结果
> seq 1 20 |grep -m 5 -E '[0-9]{2}'
10
11
12
13
14
(8)统计匹配多少行
> seq 1 20 |grep -c -E '[0-9]{2}'
11
(9)匹配b字符开头的行
> echo "a bc de" |xargs -n1 |grep '^b'
bc
(10)匹配de字符结尾的行并输出匹配的行
> echo "a ab abc abcd abcde" |xargs -n1 |grep -n 'de$'
5:abcde
(11)递归搜索/etc目录下包含ip的conf后缀文件
grep --include:只检索匹配的文件
> grep -r '192.167.1.1' /etc --include *.conf
(12)排除搜索bak后缀的文件
grep --exclude:跳过匹配的文件
> grep -r '192.167.1.1' /opt --exclude *.bak
(13)匹配所有IP
> ifconfig |grep -E -o "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
(14)打印匹配结果及后3行
> seq 1 10 |grep 5 -A 3
5
6
7
8
(15)打印匹配结果及前3行
> seq 1 10 |grep 5 -B 3
2
3
4
(16)打印匹配结果及前后3行
> seq 1 10 |grep 5 -C 3
2
3
4
5
6
7
8
三、sed
流编辑器,过滤和替换文本。
工作原理:sed命令将当前处理的行读入模式空间进行处理,处理完把结果输出,并清空模式空间。然后再将下一行读入模式空间进行处理输出,以此类推,直到最后一行。还有一个空间叫保持空间,又称暂存空间,可以暂时存放一些处理的数据,但不能直接输出,只能放到模式空间输出。
这两个空间其实就是在内存中初始化的一个内存区域,存放正在处理的数据和临时存放的数据。
语法格式:sed [选项] '地址 命令' file



借助一些文本内容作为示例:
[root@openEuler-1 script]# cat sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
blp5 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
3.1 匹配打印(p)
(1)打印匹配blp5开头的行
[root@openEuler-1 script]# sed -n '/^blp5/p' sed.txt
blp5 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
(2)打印第一行
[root@openEuler-1 script]# sed -n '1p' sed.txt
nimgtw 48003/udp # Nimbus Gateway
(3)打印第一行至第三行
[root@openEuler-1 script]# sed -n '1,3p' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
(4)打印奇数行
[root@openEuler-1 script]# seq 10 | sed -n '1~2p'
1
3
5
7
9
(5)打印匹配行及后一行
[root@openEuler-1 script]# sed -n '/blp5/,+1p' sed.txt
blp5 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
(6)打印最后一行
[root@openEuler-1 script]# sed -n '$p' sed.txt
iqobject 48619/udp # iqobject
(7)不打印最后一行
感叹号也就是对后面的命令取反。
[root@openEuler-1 script]# sed -n '$!p' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
blp5 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
(8)匹配范围blp5开头的行~com开头的行
以逗号分开两个样式选择某个范围。
[root@openEuler-1 script]# sed -n '/^blp5/,/^com/p' sed.txt
blp5 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
3.2 匹配删除(d)
删除与打印使用方法类似,打印是把匹配的打印出来,删除是把匹配的删除,删除只是不用-n选项。
(1)删除包含blp5的行
[root@openEuler-1 script]# sed '/^blp5/d' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
(2)删除1~3行
[root@openEuler-1 script]# sed '1,3d' sed.txt
isnetserv 48128/udp # Image Systems Network Services
blp5 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
(3)去除http.conf文件空行和开头#号的行
[root@openEuler-1 script]# sed '/^$/d;/.*#/d' /etc/httpd/conf/httpd.conf
3.3 替换(s///)
(1)替换blp5字符串为test
[root@openEuler-1 script]# sed 's/blp5/test/' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
test 48129/tcp # Bloomberg locator
test 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
(2)替换开头是blp5的字符串并打印
[root@openEuler-1 script]# sed -n 's/blp5/test/p' sed.txt
test 48129/tcp # Bloomberg locator
test 48129/udp # Bloomberg locator
(3)使用&命令引用匹配内容并替换
[root@openEuler-1 script]# sed 's/48049/&.0/' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049.0/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
blp5 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
(4)给IP加引号
g:全局替换
[root@openEuler-1 script]# echo "192.168.121.11 172.1.1.2 223.5.5.5" | sed -r 's/[^ ]+/“&”/g'
“192.168.121.11” “172.1.1.2” “223.5.5.5”
(5)对1-5行的blp5进行替换
[root@openEuler-1 script]# sed '1,5s/blp5/test/' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
test 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
(6)对匹配行进行替换
[root@openEuler-1 script]# sed '/48129\/tcp/s/blp5/test/' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
test 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
(7)二次匹配替换
[root@openEuler-1 script]# sed 's/blp5/test/;s/3g/4g/' sed.txt
nimgtw 48003/udp # Nimbus Gateway
4gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
test 48129/tcp # Bloomberg locator
test 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
(8)注释匹配行后的多少行
[root@openEuler-1 script]# seq 10 | sed '/5/,+3s/^/#/'
1
2
3
4
#5
#6
#7
#8
9
10
3.4 多重编辑(-e)
[root@openEuler-1 script]# sed -e '1,2d' -e 's/blp5/test/' sed.txt
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
test 48129/tcp # Bloomberg locator
test 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject# 也可以使用;分隔
[root@openEuler-1 script]# sed '1,2d;s/blp5/test/' sed.txt
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
test 48129/tcp # Bloomberg locator
test 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
3.5 添加新内容(a,i、c)
(1)在blp5上一行添加test
[root@openEuler-1 script]# sed '/blp5/i \test' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
test
blp5 48129/tcp # Bloomberg locator
test
blp5 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
(2)在blp5下一行添加test
[root@openEuler-1 script]# sed '/blp5/a \test' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
blp5 48129/tcp # Bloomberg locator
test
blp5 48129/udp # Bloomberg locator
test
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
(3)将blp5替换新行
[root@openEuler-1 script]# sed '/blp5/c \test' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
test
test
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
3.6 读取文件并追加到匹配行后(r)
[root@openEuler-1 script]# cat a.txt
123
456
[root@openEuler-1 script]# sed '/blp5/r a.txt' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
blp5 48129/tcp # Bloomberg locator
123
456
blp5 48129/udp # Bloomberg locator
123
456
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
3.7 将匹配行写入文件(w)
[root@openEuler-1 script]# sed '/blp5/w b.txt' sed.txt
nimgtw 48003/udp # Nimbus Gateway
3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
isnetserv 48128/tcp # Image Systems Network Services
isnetserv 48128/udp # Image Systems Network Services
blp5 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
com-bardac-dw 48556/tcp # com-bardac-dw
com-bardac-dw 48556/udp # com-bardac-dw
iqobject 48619/tcp # iqobject
iqobject 48619/udp # iqobject
[root@openEuler-1 script]# cat b.txt
blp5 48129/tcp # Bloomberg locator
blp5 48129/udp # Bloomberg locator
3.8 读取下一行(n和N)
n 读取下一行到模式空间。
N 追加下一行内容到模式空间,并以换行符\n分隔。
(1)打印匹配的下一行
[root@openEuler-1 script]# seq 5 |sed -n '/3/{n;p}'
4
(2)打印偶数
[root@openEuler-1 script]# seq 10 | sed -n 'n;p'
2
4
6
8
10
# sed先读取第一行1,执行n命令,获取下一行2,此时模式空间是2,
# 执行p命令,打印模式空间。 现在模式空间是2,sed再读取3,
# 执行n命令,获取下一行4,此时模式空间为4,执行p命令,以此类推.
(3)打印奇数
[root@openEuler-1 script]# seq 10 |sed 'n;d'
1
3
5
7
9
# sed先读取第一行1,此时模式空间是1,并打印模式空间1,
# 执行n命令,获取下一行2,执行d命令,删除模式空间的2,sed再读取3,
# 此时模式空间是3,并打印模式空间,再执行n命令,获取下一行4,
# 执行d命令,删除模式空间的3,以此类推.
3.9 打印和删除模式空间的第一行(P和D)
P 打印模式空间的第一行。
D 删除模式空间的第一行。
(1)打印奇数
[root@openEuler-1 script]# seq 6 | sed -n 'N;P'
1
3
5
(2)保留最后一行
[root@openEuler-1 script]# seq 6 | sed 'N;D'
6
# 读取第一行1,执行N命令读取下一行并追加到模式空间,
# 此时模式空间是1\n2,执行D命令删除模式空间第一行1,剩余2.
# 读取第二行,执行N命令,此时模式空间是3\n4,
# 执行D命令删除模式空间第一行3,剩余4,以此类推.
3.10 保持空间操作(h与H、g与G和x)
h 复制模式空间内容到保持空间(覆盖)。
H 复制模式空间内容追加到保持空间。
g 复制保持空间内容到模式空间(覆盖)。
G 复制保持空间内容追加到模式空间。
x 模式空间与保持空间内容互换。
(1)将匹配的内容覆盖到另一个匹配
[root@openEuler-1 script]# seq 6 | sed -e '/3/{h;d}' -e '/5/g'
1
2
4
3
6
# h命令把匹配的3复制到保持空间,d命令删除模式空间的3.
# 后面命令再对模式空间匹配5,并用g命令把保持空间3覆盖模式空间5.
(2)将匹配的内容放到最后
[root@openEuler-1 script]# seq 6 | sed -e '/3/{h;d}' -e '$G'
1
2
4
5
6
3
# 这里的$代表最后一行,G表示将保持空间的内容追加到当前行的后面
(3)交换模式空间和保持空间
[root@openEuler-1 script]# seq 6 | sed -e '/3/{h;d}' -e '/5/x' -e '$G'
1
2
4
3
6
5
# 在模式空间匹配5并将保持空间的3与5交换,5就变成了3.
# 最后把保持空间的5追加到模式空间.
(4)倒序输出
[root@openEuler-1 script]# seq 5 |sed '1!G;h;$!d'
5
4
3
2
1
# 1!G 第一行不执行把保持空间内容追加到模式空间,因为现在保持空间还没有数据
# h 将模式空间放到保持空间暂存
# $!d 最后一行不执行删除模式空间的内容。
(5)每行后面添加新空行
[root@openEuler-1 script]# seq 5 |sed G
12345
3.11 忽略大小写匹配(I)
[root@openEuler-1 script]# echo -e "a\nA\nb\nc" |sed 's/a/1/Ig'
1
1
b
c
3.12 获取总行数
[root@openEuler-1 script]# seq 10 |sed -n '$='
10
四、awk
awk 是一个处理文本的编程语言工具,能用简短的程序处理标准输入或文件、数据排序、计算以及 生成报表等。
基本的命令语法:awk option 'pattern {action}' file
其中pattern表示AWK在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令。花括号用于根据特定的模式对一系列指令进行分组。
awk 处理的工作方式与数据库类似,支持对记录和字段处理,这也是grep和sed不能实现的。在awk中,缺省的情况下将文本文件中的一行视为一个记录,逐行放到内存中处理,而将一行中的某一部分作为记录中的一个字段。用1,2,3...数字的方式顺序的表示行(记录)中的不同字段。用$后跟数字,引用对应的字段,以逗号分隔,0表示整个行。

4.1 选项、模式


(1)从文件读取awk程序处理文件
[root@openEuler-1 script]# cat test.awk
{print $2}
[root@openEuler-1 script]# tail -n3 /etc/services | awk -f test.awk
45514/udp
45514/tcp
46998/tcp
(2)指定分隔符,打印指定字段(默认以空格分割)
[root@openEuler-1 script]# tail -n3 /etc/passwd | awk -F':' '{print $1}'
apache
mysql
nginx
(3)指定多个分隔符作为同一个分隔符处理
[root@openEuler-1 script]# tail -n3 /etc/services
cloudcheck-ping 45514/udp # ASSIA CloudCheck WiFi Management keepalive
cloudcheck 45514/tcp # ASSIA CloudCheck WiFi Management System
spremotetablet 46998/tcp # Capture handwritten signatures[root@openEuler-1 script]# tail -n3 /etc/services | awk -F'[/#]' '{print $1}'
cloudcheck-ping 45514
cloudcheck 45514
spremotetablet 46998
[root@openEuler-1 script]# tail -n3 /etc/services | awk -F'[/#]' '{print $2}'
udp
tcp
tcp
[root@openEuler-1 script]# tail -n3 /etc/services | awk -F'[/#]' '{print $3}'ASSIA CloudCheck WiFi Management keepaliveASSIA CloudCheck WiFi Management SystemCapture handwritten signatures
(4)变量赋值
[root@openEuler-1 script]# awk -v a=123 'BEGIN{print a}'
123
(5)输出awk全局变量到文件
[root@openEuler-1 script]# seq 5 | awk --dump-variables '{print $0}'
1
2
3
4
5
[root@openEuler-1 script]# cat awkvars.out
ARGC: 1
ARGIND: 0
ARGV: array, 1 elements
BINMODE: 0
CONVFMT: "%.6g"
ENVIRON: array, 25 elements
ERRNO: ""
FIELDWIDTHS: ""
FILENAME: "-"
FNR: 5
FPAT: "[^[:space:]]+"
FS: " "
FUNCTAB: array, 41 elements
IGNORECASE: 0
LINT: 0
NF: 1
NR: 5
OFMT: "%.6g"
OFS: " "
ORS: "\n"
PREC: 53
PROCINFO: array, 21 elements
RLENGTH: 0
ROUNDMODE: "N"
RS: "\n"
RSTART: 0
RT: "\n"
SUBSEP: "\034"
SYMTAB: array, 28 elements
TEXTDOMAIN: "messages"
(6)BEGIN和END
BEGIN模式是在处理文件之前执行该操作,常用于修改内置变量、变量赋值和打印输出的页眉或标 题。END模式是在程序处理完才会执行。
示例:
[root@openEuler-1 script]# cat frequent_ip.sh
#!/bin/bash
#########################
#File name:frequent_ip.sh
#Email:obboda@163.com
#Created time:2025-01-14 11:46:11
#Description:访问nginx日志,得到访问ip最多的前10个
#########################log_path="/var/log/nginx/access.log"# 拿取按照访问次数排序过的ip
sort_data=`awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c`# 按照sort_data的数据进行优化处理,打印输出
echo "$sort_data" | awk '
BEGIN{printf "%-10s %-10s %-10s \n","访问排名","访问IP","访问次数"}
{printf "%-10s %-20s %-10s \n",NR,$2,$1}
END{print "end............"}
'
[root@openEuler-1 script]# bash frequent_ip.sh
访问排名 访问IP 访问次数
1 192.168.121.1 8
2 192.168.121.12 3
3 192.168.121.13 2
4 192.168.121.131 1
5 192.168.121.51 4
end............
4.2 内置变量


(1)FS和OFS
在程序开始前重新赋值FS变量,改变默认分隔符为冒号,与-F一样。
[root@openEuler-1 script]# head -n5 /etc/passwd | awk 'BEGIN{FS=":"}{print $1,$2}'
root x
bin x
daemon x
adm x
lp x# 也可以使用-v来重新赋值这个变量,并指定输出分隔符
[root@openEuler-1 script]# head -n5 /etc/passwd | awk -vFS=':' '{print $1,$2}'
root x
bin x
daemon x
adm x
lp x# 也可以指定输出分隔符
[root@openEuler-1 script]# head -n5 /etc/passwd | awk 'BEGIN{FS=":";OFS="#"}{print $1,$2}'
root#x
bin#x
daemon#x
adm#x
lp#x
(2)RS和ORS
# 指定以某个字符作为分隔符来处理记录:
[root@openEuler-1 script]# echo "www.baidu.com/user/test.html" |awk 'BEGIN{RS="/"}{print $0}'
www.baidu.com
user
test.html# 将输出的换行符替换为+号:
[root@openEuler-1 script]# seq 10 | awk 'BEGIN{ORS="+"}{print $0}'
1+2+3+4+5+6+7+8+9+10+[root@openEuler-1 script]#
(3)NF
# NF是字段个数
[root@openEuler-1 script]# echo "a b c d e f" | awk '{print NF}'
6# 打印最后一个字段
[root@openEuler-1 script]# echo "a b c d e f" | awk '{print $NF}'
f
(4)NR和FNR
NR统计记录编号,每处理一行记录,编号就会+1,FNR不同的是在统计第二个文件时会重新计数。
[root@openEuler-1 script]# tail -n5 /etc/services | awk '{print NR,$0}'
1 axio-disc 35100/udp # Axiomatic discovery protocol
2 pmwebapi 44323/tcp # Performance Co-Pilot client HTTP API
3 cloudcheck-ping 45514/udp # ASSIA CloudCheck WiFi Management keepalive
4 cloudcheck 45514/tcp # ASSIA CloudCheck WiFi Management System
5 spremotetablet 46998/tcp # Capture handwritten signatures
NR和FNR的区别:
[root@openEuler-1 script]# awk '{print NR,FNR,$0}' a b
1 1 a
2 2 b
3 3 c
4 1 d
5 2 e
6 3 f
(5)ARGC和ARGV
ARGC是命令行参数数量
ARGV是将命令行参数存到数组,元素由ARGC指定,数组下标从0开始
[root@openEuler-1 script]# awk 'BEGIN{print ARGC}' 1 2 3
4
[root@openEuler-1 script]# awk 'BEGIN{print ARGV[0],ARGV[1]}' 1 2 3
awk 1
(6)ARGIND
ARGIND是当前正在处理的文件索引值,第一个文件是1,第二个文件是2,以此类推,从而可以通过这种方式判断正在处理哪个文件。
[root@openEuler-1 script]# awk '{print ARGIND,$0}' a b
1 a
1 b
1 c
2 d
2 e
2 f
(7)ENVIRON
ENVIRON调用系统变量。
[root@openEuler-1 script]# awk 'BEGIN{print ENVIRON["HOME"]}'
/root
(8)FILENAME
FILENAME是当前处理文件的文件名。
[root@openEuler-1 script]# awk '{print FILENAME,$0}' a b
a a
a b
a c
b d
b e
b f
(9)IGNORECASE
IGNORECASE=1表示忽略大小写
[root@openEuler-1 script]# echo "A a b c" |xargs -n1 |awk 'BEGIN{IGNORECASE=1}/a/'
A
a
4.3 操作符

注意:在awk中,有3种情况表达式为假:数字是0,空字符串和未定义的值。且数值运算,未定义变量初始值为0。字符运算,未定义变量初始值为空。
(1)截取整数
[root@openEuler-1 script]# echo "123abc abc123 123abc123" |xargs -n1 | awk '{print +$0}'
123
0
123[root@openEuler-1 script]# echo "123abc abc123 123abc123" |xargs -n1 | awk '{print -$0}'
-123
0
-123
(2)打印奇数偶数行
# 打印奇数行
[root@openEuler-1 script]# seq 6 | awk 'i=!i'
1
3
5# 打印偶数行
[root@openEuler-1 script]# seq 6 | awk '!(i=!i)'
2
4
6
(3)管道符的使用
[root@openEuler-1 script]# seq 5 | shuf | awk '{print $0|"sort"}'
1
2
3
4
5
# 其中shuf会将原来的顺序打乱
(4)三目运算符
[root@openEuler-1 script]# awk 'BEGIN{print 1==1?"yes":"no"}'
yes
4.4 流程控制
(1)if语句
格式:if (condition) statement [ else statement ]
# 单分支
[root@openEuler-1 script]# seq 5 | awk '{if($0==3)print $0}'
3# 双分支
[root@openEuler-1 script]# seq 5 |awk '{if($0==3)print $0;else print "no"}'
no
no
3
no
no
(2)while语句
格式:while (condition) statement
[root@openEuler-1 script]# echo "1 2 3 4 5" | awk '{i=1;while(i<=NF){print $i;i++}}'
1
2
3
4
5
(3)for语句C语言风格
格式:for (expr1; expr2; expr3) statement
[root@openEuler-1 script]# cat file
1 2 3
4 5 6
7 8 9
[root@openEuler-1 script]# awk '{for(i=1;i<=NF;i++)print $i}' file
1
2
3
4
5
6
7
8
9
(4)for语句遍历数组
格式:for (var in array) statement
[root@openEuler-1 script]# seq -f "str%.g" 5 |awk '{a[NR]=$0}END{for(v in a)print v,a[v]}'
1 str1
2 str2
3 str3
4 str4
5 str5
(5)break和continue语句
break跳过所有循环,continue跳过当前循环。
[root@openEuler-1 script]# awk 'BEGIN{for(i=1;i<=5;i++){if(i==3){break};print i}}'
1
2
[root@openEuler-1 script]# awk 'BEGIN{for(i=1;i<=5;i++){if(i==3){continue};print i}}'
1
2
4
5
(6)exit语句
格式:exit [ expression ]
exit退出程序,与shell的exit一样。[ expr ]是0-255之间的数字。
[root@openEuler-1 script]# seq 5 |awk '{if($0~/3/)exit (123)}'
[root@openEuler-1 script]# echo $?
123
4.5 内置函数


[root@openEuler-1 script]# cat c
123abc
abc123
123abc123
[root@openEuler-1 script]# awk '{print int($0)}' c
123
0
123
4.6 I/O语句


# 获取匹配行的下一行
[root@openEuler-1 script]# seq 5 |awk '/3/{getline;print}'
4
4.7 printf语句
格式化输出,默认打印字符串不换行。
格式:printf [format] arguments

# 左对齐宽度10
[root@openEuler-1 script]# awk 'BEGIN{printf "%-10s %-10s %-10s\n","ID","Name","Passwd"}'
ID Name Passwd
相关文章:
Shell正则表达式与文本处理三剑客(grep、sed、awk)
一、正则表达式 Shell正则表达式分为两种: 基础正则表达式:BRE(basic regular express) 扩展正则表达式:ERE(extend regular express),扩展的表达式有、?、|和() 1.1 基本正则表…...
Docker Desktop 中安装 MySQL 并开启远程访问的详细教程
是在 Docker Desktop 中安装 MySQL 并开启远程访问的详细教程: 一、安装 MySQL 容器 拉取 MySQL 镜像: docker pull mysql:latest这将从 Docker Hub 上拉取最新版本的 MySQL 镜像。如果你想使用特定版本的 MySQL,可以将 latest 替换为具体…...
计算机网络 (39)TCP的运输连接管理
前言 TCP(传输控制协议)是一种面向连接的、可靠的传输协议,它在计算机网络中扮演着至关重要的角色。TCP的运输连接管理涉及连接建立、数据传送和连接释放三个阶段。 一、TCP的连接建立 TCP的连接建立采用三次握手机制,其过程如下&…...
麦田物语学习笔记:构建游戏的时间系统
基本流程 1.代码思路 (1)新建一个TimeManager.cs (2)创建枚举变量来表示四季,在TimeManager里需要的变量有: 游戏内的秒,分钟,小时,天,月,年;游戏内的季节;控制一个季节有多少个月;控制时间的暂停;计时器tikTime (3)在Settings里添加计时器的阈值,以及各个时间的进位 (4)初始化…...
Tauri教程-进阶篇-第二节 命令机制
“如果结果不如你所愿,就在尘埃落定前奋力一搏。”——《夏目友人帐》 “有些事不是看到了希望才去坚持,而是因为坚持才会看到希望。”——《十宗罪》 “维持现状意味着空耗你的努力和生命。”——纪伯伦 Tauri 技术教程 * 第五章 Tauri的进阶教程 第二节…...
candb++ windows11运行报错,找不到mfc140.dll
解决问题记录 mfc140.dll下载 注意:放置位置别搞错了...
提供的 IP 地址 10.0.0.5 和子网掩码位 /26 来计算相关的网络信息
网络和IP地址计算器 https://www.sojson.com/convert/subnetmask.html提供的 IP 地址 10.0.0.5 和子网掩码位 /26 来计算相关的网络信息。 子网掩码转换 子网掩码 /26 的含义二进制表示:/26 表示前 26 位是网络部分,剩下的 6 位是主机部分。对应的子网掩码为 255…...
vscode离线安装插件--终极解决方案
目录 离线安装插件安装方法 vscode连接远程服务器中的docker远程连接python jupyter开发 离线安装插件 使用vscode开发过程中,有一些内网服务器没法连接外网,造成安装插件不方便,网络上很多文章提供了很多方法,比较常见的一种是&…...
LabVIEW启动时Access Violation 0xC0000005错误
问题描述 在启动LabVIEW时,可能出现程序崩溃并提示以下错误:Error 0xC0000005 (Access Violation) Access Violation错误通常是由于权限不足、文件冲突或驱动问题引起的。以下是解决此问题的全面优化方案: 解决步骤 1. 以管理员身份运行…...
string(一)
一、了解string 可以看成是字符顺序表。 二、string遍历方式 1、下标[ ] 重载了[] for(int i 0; i < s.size(); i) {cout << s[i]; } 2、迭代器 auto it s.begin(); while(it ! s.end()) {cout << *it;it; } 3、范围for for(auto ch : s) {cout <&l…...
计算机网络 (41)文件传送协议
前言 一、文件传送协议(FTP) 概述: FTP(File Transfer Protocol)是互联网上使用得最广泛的文件传送协议。FTP提供交互式的访问,允许客户指明文件的类型与格式(如指明是否使用ASCII码࿰…...
C++ STL之容器介绍(vector、list、set、map)
1 STL基本概念 C有两大思想,面向对象和泛型编程。泛型编程指编写代码时不必指定具体的数据类型,而是使用模板来代替实际类型,这样编写的函数或类可以在之后应用于各种数据类型。而STL就是C泛型编程的一个杰出例子。STL(Standard …...
redisson 连接 redis5报错 ERR wrong number of arguments for ‘auth‘ command
依赖版本 org.redisson:redisson-spring-boot-starter:3.25.2 现象 启动报错 org.redisson.client.RedisException: ERR wrong number of arguments for ‘auth’ command. channel: [xxx] command: (AUTH), params: (password masked) 原因 redis6以下版本认证参数不包含用…...
LeetCode:131. 分割回文串
跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:131. 分割回文串 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文串。返回 s 所…...
React-useState讲解
useState 让页面“动”起来 例如实现一个 click 计数功能,普通变量无法实现。即:修改普通变量无法触发组件的更新 rerender 通过 useState 即可实现。 state 是什么 State, A component’s memory —— 这个比喻非常好! props 父组件传…...
混币器是什么,波卡跨链交易平台
混币器是什么 混币器是一种加密货币工具,主要功能是将用户的加密货币与其他众多用户的加密货币混合在一起,打乱资金的流向和交易痕迹,使得加密货币的来源和去向难以追踪,从而增加交易的匿名性和隐私性。以下是对其工作流程和相关举例的介绍: 工作流程 用户首先将自己的加…...
【PHP】双方接口通信校验服务
请求方 使用 ApiAuthService::buildUrl($domain, [terminal > 1, ts > time()]); //http://域名/adminapi/login/platformLogin?signF7FE8A150DEC18BE8A71C5059742C81A&terminal1&ts1736904841接收方 $getParams $this->request->get();$validate ApiA…...
Web第一次作业
目录 题目 html代码 index login register css代码 base index login register 效果展示 index login register 题目 实现一个登录页面、实现一个注册页面;实现一个主页 - 登录页面:login.html - 注册页面:register.html - 主页…...
CentOS 6.8 安装 Nginx
个人博客地址:CentOS 6.8 安装 Nginx | 一张假钞的真实世界 提前安装: # sudo yum install yum-utils 一般情况下这个工具系统已经安装。 创建文件/etc/yum.repos.d/nginx.repo,输入内容如下: [nginx-stable] namenginx stab…...
网络网络层ICMP协议
网络网络层ICMP协议 1. ICMP 协议介绍 ICMP(Internet Control Message Protocol)是 TCP/IP 协议簇中的网络层控制报文协议。用于在 IP 主机、路由器之间传递控制消息,提供可能有关通信问题的反馈信息。 以及用于网络诊断或调试(…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
