ℹ️大家好,我是练小杰,今天是2025年第一天,元旦快乐各位😆
本文是有关Linux shell脚本编程的awk命令详解,后续我会不断增加相关内容 ~~
回忆:【awk编程语言(1)】
更多Linux 相关内容请点击👉【Linux专栏】~
文章目录
awk内置字符串函数
length(x) 返回x
的长度
- 打印文件lxj.txt中,若长度为x>=2时,输出动作
awk '{x=$1;y=$2;if(length(x)>=2) print "$1 is:" x}' lxj.txt
$1 is:It
$1 is:It
gsub( )函数
gsub()
函数的返回值是替换的个数!gsub( )
只对内存中的内容起作用,并不修改文件本身!gsub(r,s)
在整个$0
中用s
替代r
- gsub(r,s,t) 在整个
t
中用s
替代r
[root@localhost ~]# cat Ftest.txt
127.0.0.1; ? localhost? localhost.localdomain localhost4 ;localhost4.localdomain4
::1;space? localhost? localhost.localdomain localhost6; localhost6.localdomain6
[root@localhost ~]# awk '{print gsub("local","127")}' Ftest.txt
6
6
可以看到,说明在上述例子中,127 替换了6个local!
- 利用gsub( )函数把
bed
替换good
文件内容
[root@localhost ~]# echo "you are bed boy">lxj.txt
[root@localhost ~]# awk '{gsub("bed","good")} {print}' lxj.txt
you are good boy
index 函数
index(s1, s2) 函数用于查找字符串 s2 在字符串 s1 中第一次出现的位置。
如果找到,返回 s2 在 s1 中第一次出现的位置(从 1 开始计数);如果未找到,则返回 0。
- 基本语法:
index(s1, s2)
s1: 要搜索的主字符串
s2: 要查找的目标字符串
基本用法
- 假设有文本文件 example.txt,内容为
Hello, world!
awk is a good tool.
Hello again!
- 使用 index 函数查找 “world” 在每一行中的位置
awk '{print index($0, "world")}' example.txt
输出结果:
8
0
0
可以看到,第一行 “Hello, world!” 中,“world” 从第 8 个字符开始。
第二行和第三行中不包含 “world”,因此返回 0。
- 查找子字符串的位置
echo "The quick brown over the lazy dog" | awk '{print index($0, "brown")}'
输出结果:
11
可以看到,“brown” 在字符串中的位置是第 11 个字符
实际用法
- 假设有一个包含多个 URL 的文件
urls.txt
:
https://blog.csdn.net/weixin_55767624
https://www.example.com
ftp://fileserver.com
https://secure.example.com/login
- 要查找包含 “example” 的 URL,可以使用 index 函数:
awk 'index($0, "example") > 0' urls.txt
输出:
https://www.example.com
https://secure.example.com/login
说明:
index($0, "example") > 0
表示当 “example” 在行中出现的位置大于 0 时,即该行包含 “example”
match 函数
match(s, r)
函数用于在字符串 s 中查找正则表达式 r 的匹配。如果找到,返回匹配字符串的起始位置(从 1 开始计数);如果未找到,则返回 0。match
函数还会设置两个内置变量:RSTART
和RLENGTH
,分别表示匹配字符串的起始位置和长度
语法格式:
match(s, r)
s
: 要搜索的主字符串
r
: 要匹配的正则表达式
基本用法
- 假设有以下文本文件 example.txt
Hello, lxj!
awk is a powerful tool.
Hello again!
- 使用
match
函数查找 “lxj” 在每一行中的位置:
awk '{pos = match($0, /lxj/); print pos}' example.txt
输出结果:
8
0
0
第一行 “
Hello, lxj!
” 中,“lxj” 从第 8 个字符开始
第二行和第三行中不包含 “world”,因此返回 0
使用 RSTART 和 RLENGTH
match 函数设置了 RSTART 和 RLENGTH 两个内置变量
RSTART
: 匹配字符串的起始位置RLENGTH
: 匹配字符串的长度
echo "The quick brown fox jumps over the lazy dog" | awk '{
match($0, /brown/);
print "Position: " RSTART ", Length: " RLENGTH
}'
输出结果:
Position: 11, Length: 5
由此可知,“brown” 在字符串中的位置是第 11 个字符,长度为 5。
match 函数的实际应用
- 查找并处理匹配的部分
- 假设有一个包含电子邮件地址的文件 emails.txt
Alice <alice@example.com>
Bob bob@test.com
Charlie: charlie@domain.org
- 要查找所有电子邮件地址并提取用户名和域名
awk '{
if (match($0, /<([^>]+)>|[^[:space:]:]+@[^[:space:]:]+/)) {
email = substr($0, RSTART, RLENGTH);
if (email ~ /<([^>]+)>/) {
username = substr(email, 2, length(email) - 2);
} else {
username = email;
}
split(email, parts, "@");
domain = parts[2];
print "Username: " username ", Domain: " domain
}
}' emails.txt
- 输出结果
Username: alice, Domain: example.com
Username: bob, Domain: test.com
Username: charlie, Domain: domain.org
说明:
1.match
函数查找符合电子邮件地址模式的字符串。
2.使用substr
提取电子邮件地址。
3.使用正则表达式判断是否包含 < 和 >,并提取用户名。
4.使用split
函数分割电子邮件地址,提取域名。
5.打印用户名和域名。
- 查找并替换匹配的部分
- 有一个包含日期的文件 dates.txt
Today is 2023-10-05.
The event is scheduled for 2023/11/25.
Last updated on 2023.12.31.
- 要将日期格式统一为 YYYY-MM-DD
awk '{
while (match($0, /[0-9]{4}[-/][0-9]{2}[-/][0-9]{2}/)) {
date = substr($0, RSTART, RLENGTH);
gsub(/-/, "/", date);
sub(/[0-9]{4}[-/][0-9]{2}[-/][0-9]{2}/, date, $0);
}
print
}' dates.txt
- 输出结果:
Today is 2023-10-05.
The event is scheduled for 2023/11/25.
Last updated on 2023/12/31.
说明:
match
函数查找符合日期格式的字符串。- 使用
substr
提取日期。- 使用
gsub
将-
替换为/
- 使用
sub
将原始日期替换为新的日期格式。- 重复上述过程直到所有日期都被处理。
- 打印处理后的行。
awk内置变量
- 变量提高了awk程序可读性
行号:NG
ls -l | awk '{print NR,$0}'
1 total 24
2 -rw-------. 1 root root 2767 Jun 10 2020 anaconda-ks.cfg
3 drwxr-xr-x. 2 root root 6 May 7 2021 Desktop
4 drwxr-xr-x. 2 root root 6 Jun 10 2020 Documents
5 drwxr-xr-x. 2 root root 6 Jun 10 2020 Downloads
6 drwxr-xr-x. 2 root root 6 Jun 10 2020 Music
7 -rwxr--r--. 1 root root 28 Mar 30 2021 net.sh
8 -rw-------. 1 root root 2047 Jun 10 2020 original-ks.cfg
9 drwxr-xr-x. 2 root root 6 Jun 10 2020 Pictures
10 -rw-r--r--. 1 root root 298 Apr 12 01:37 printf.sh
11 drwxr-xr-x. 2 root root 6 Jun 10 2020 Public
12 drwxr-xr-x. 2 root root 6 Jun 10 2020 Templates
13 -rw-r--r--. 1 root root 467 Apr 12 08:16 test1.txt
14 -rw-r--r--. 1 root root 167 Apr 12 08:00 test.txt
15 drwxr-xr-x. 2 root root 6 Jun 10 2020 Videos
NF:域个数
- 利用NF变量输出域个数
[root@localhost ~]# ls -l | awk '{print NF,$0}'
2 total 24
9 -rw-------. 1 root root 2767 Jun 10 2020 anaconda-ks.cfg
9 drwxr-xr-x. 2 root root 6 May 7 2021 Desktop
9 drwxr-xr-x. 2 root root 6 Jun 10 2020 Documents
9 drwxr-xr-x. 2 root root 6 Jun 10 2020 Downloads
9 drwxr-xr-x. 2 root root 6 Jun 10 2020 Music
[root@localhost ~]# awk '{print NF}' /etc/hosts
5
5
[root@localhost ~]# awk '{print NF,$5}' /etc/hosts
5 localhost4.localdomain4
5 localhost6.localdomain6
[root@localhost ~]# awk '{print $NF}' /etc/hosts
localhost4.localdomain4
localhost6.localdomain6
NR与FNR
NR
将所有文件的数据视为一个数据流。FNR
则是将多个文件的数据视为独立的若干个数据流,遇到新文件时行号从1开始重新递增。
[root@localhost ~]# awk '{print NR "\t"$1}' /etc/hosts test.txt
1 127.0.0.1
2 ::1
1 127.0.0.1
2 ::1;
[root@localhost ~]# awk '{print FNR, "\t",$1}' /etc/hosts test.txt
1 127.0.0.1
2 ::1
1 127.0.0.1
2 ::1;
自定义变量
[root@localhost ~]# awk -v x="hello" -v y="OK" '{print x,y}' /etc/hosts
hello OK
hello OK
[root@localhost ~]# awk -v shell=$SHELL '{print shell}' /etc/hosts #调用系统变量
/bin/bash
/bin/bash
[root@localhost ~]# awk '{print "'$SHELL'"}' /etc/hosts
/bin/bash
/bin/bash
内置变量RS、OFS、ORS区别
- RS变量
内置变量RS保存的是输入数据的行分隔符,默认为\n
,可以指定其它字符作为行分隔符
awk -v RS="." '{print $1}' /etc/hosts
127
0
0
1
localdomain
localdomain4
localdomain
localdomain6
- OFS变量
保存的是输出字段的分隔符(列分隔符),默认为空格
awk -v OFS="," '{print $1,$2,$3}' /etc/hosts
127.0.0.1,localhost,localhost.localdomain
::1,localhost,localhost.localdomain
- ORS变量
保存的是输出记录的分隔符
awk -v ORS="@" '{print $1,$2,$3}' /etc/hosts
127.0.0.1 localhost
localhost.localdomain@::1 localhost
localhost.localdomain@
今天awk的内容就到这里,蛇年来啦😆
如果想了解更多,点击主页【练小杰的CSDN】
⚠️若博客里的内容有问题,欢迎指正,我会及时修改!!!
明天再见,各位🧍♂️大佬们~~