awk实战经典实战案例

1.插入几个新字段
在”a b c d”的b后面插入3个e f g
[root@iZbp1cr1sgiqi6r6qlygx9Z ~]# echo ” a b c d ” | awk ‘{$2=$2 ” e f g”;print}’
a b e f g c d
awk中重新赋值后,awk会重新构建$0,也就是重构后的一行的数据

2.格式化个空白
移除每行的前缀、后缀空白,并将各部分左对齐

  aaaa    bbbb    cccc

bbb aaa ccc
ddd fff eee ggg hhhh iii jjj

awk ‘BEGIN{OFS=”\t”}{$1=$1;print}’ 11.txt
awk ‘{$1=$1;print}’ 11.txt

3.筛选IPV4地址
[root@www test]# ifconfig
br-4d64a44d0b5a: flags=4099 mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:05:3f:6a:7f txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

docker0: flags=4099 mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:64:72:b8:e9 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

ens33: flags=4163 mtu 1500
inet 192.168.75.142 netmask 255.255.255.0 broadcast 192.168.75.255
inet6 fe80::e78c:a86e:3457:f77b prefixlen 64 scopeid 0x20
ether 00:0c:29:b5:49:c8 txqueuelen 1000 (Ethernet)
RX packets 37520 bytes 3100182 (2.9 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 99410 bytes 7526954 (7.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73 mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
loop txqueuelen 1000 (Local Loopback)
RX packets 2448 bytes 274656 (268.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2448 bytes 274656 (268.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

virbr0: flags=4099 mtu 1500
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
ether 52:54:00:f7:4f:47 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

从ifcofig命令的结果中筛选出除了lo网卡外的所有IPV4地址

本机的所有网卡的IP地址
ifconfig | awk ‘/inet / && !($2 ~ /^127/){print $2}’
BEGIN{RS=””}: 这部分设置记录分隔符RS为空字符串,意味着awk将连续的一行视为一个记录,而不是默认的换行符。
ifconfig | awk ‘BEGIN{RS=””}1/io/{print $6}’
根据某字段去重
去掉uid=xxx重复的行

2019-01-13_12:00_index?uid=123
2019-01-13_13:00_index?uid=123
2019-01-13_14:00_index?uid=333
2019-01-13_15:00_index?uid=9710
2019-01-14_12:00_index?uid=123
2019-01-14_13:00_index?uid=123
2019-01-15_14:00_index?uid=333
2019-01-16_15:00_index?uid=9710

awk -F “?” ‘!a[$2]++{print}’ 13.txt
系数统计

portmapper
portmapper
portmapper
portmapper
portmapper
portmapper
status
status
mountd
mountd
mountd
mountd
mountd
mountd
nfs
nfs
nfs_acl
nfs
nfs
nfs_acl
nlockmgr
nlockmgr
nlockmgr
nlockmgr
nlockmgr

awk ‘{a[$0]++}END{OFS=”\t”;for(i in a ){print arr[i], i}}’

统计独立IP
a.com.cn|202.109.134.23|2015-11-20 20:34:43|guest
b.com.cn|202.109.134.23|2015-11-20 20:34:48|guest
c.com.cn|202.109.134.24|2015-11-20 20:34:48|guest
a.com.cn|202.109.134.23|2015-11-20 20:34:43|guest
a.com.cn|202.109.134.24|2015-11-20 20:34:43|guest
b.com.cn|202.109.134.25|2015-11-20 20:34:48|guest

在解释这个 awk 命令之前,我们先了解一下 awk 的 FPAT 变量和它的作用。FPAT(Field Pattern)是 gawk(GNU awk)特有的一个功能,它允许用户指定一个正则表达式来定义字段的分隔符,而不是传统的基于单个字符(如空格、制表符等)的分隔。

name,age,city
John Doe,30,”New York, NY”
Jane Smith,25,”Los Angeles, CA”
[^,]+:这部分匹配一个或多个非逗号字符。这意呀着,如果一行中的字符之间没有用逗号分隔,它们会被视为一个字段。

awk ‘BEGIN{FPAT=”[^,]+|\”.*\””}{print $3}’ 16.txt

[root@iZbp1cr1sgiqi6r6qlygx9Z ~]# awk ‘BEGIN{FPAT=”[^,]+|\”.\””}{print $3}’ 16.txt city “New York, NY” “Los Angeles, CA” \”.\”:这部分匹配被双引号包围的任意字符序列(包括零个字符,尽管这在实际应用中可能不是很有用)。这允许字段值包含逗号或其他特殊字符,只要这些字符被双引号包围。
{FPAT=”[^,]+|\”.*\”

\”.*\”:这部分匹配被双引号包围的任意字符(包括零个字符,尽管在实际使用中这种情况很少见且可能不是预期的)。双引号(”)在 AWK 中是特殊字符,因此需要用反斜杠(\)进行转义。这个模式允许字段包含逗号、空格或其他任何字符,只要它们被双引号包围。

在 AWK(特别是 GNU AWK,也称为 gawk)中,双引号(”)用于定义字符串字面量。当你想要在字符串内部使用双引号时,就需要对它们进行转义,以避免字符串的提前结束。转义是通过在双引号前面加上反斜杠(\)来实现的,这样 AWK 解释器就知道这个双引号是字符串的一部分,而不是用来标记字符串结束的。

然而,值得注意的是,在某些情况下,你可能不需要转义双引号,这取决于你是如何定义字符串的。

使用单引号定义字符串:如果你使用单引号(’)来定义字符串,那么字符串内部的双引号就不需要转义,因为单引号内的所有内容(除了单引号本身和通过转义引入的单引号)都被视为字符串的一部分。

name1 exampleText
name2 anotherExample
name3 moreTextHere

substr($2,1,3):是awk的一个内置函数,用于从第二个字段($2)中提取子字符串。这里,它从第二个字段的第一个字符开始(1),提取长度为3的子字符串。
print $1,substr($2,1,3):将第一个字段和第二个字段的前三个字符打印出来,它们之间默认用空格分隔。
[root@iZbp1cr1sgiqi6r6qlygx9Z ~]# awk ‘{print $1,substr($2,1,3)}’ 17.txt
name1 exa
name2 ano
name3 mor

    if($1 in arr){
            arr[$1] = arr[$1]" "$2
    }else{
    arr[$1] = $2
    }

}

END{
for(i in arr){
printf “%s %s\n”,i,arr[i]
}
}

apple red
apple green
banana yellow
apple blue
banana orange

apple red green blue
banana yellow orange

处理块({}):
如果$1(第一列的值)已经作为键存在于数组arr中,则将$2(第二列的值)追加到该键对应的值之后,中间用空格分隔。
如果$1不在arr中,则将$1作为新键,$2作为该键的值存入arr。
END块:
当所有输入行都被处理完毕后,END块会被执行。
遍历数组arr,使用printf函数打印出每个键(i)及其对应的值(arr[i]),键和值之间用空格分隔
字符串拆分
[root@iZbp1cr1sgiqi6r6qlygx9Z text]# echo “hello” | awk ‘{for(i=1;i<=length($0);i++)print substr($0,i,1)}’
h
e
l
l
o
echo “‘hello’,’world'” | sed “s/’/,/g” | awk -F, ‘{for(i=1;i<=NF;i++) print $i}’

去除文本第一行和最后一行
seq 5 | awk ‘NR>2’
seq 5 | awk ‘NR>2{print prev}{prev=$0}’
seq 5 | awk ‘NR>2{print s}{s=$0}’

当 NR(当前行号)大于2时,即从第三行开始,执行 {print s}。但注意,这里 s 在每行执行前都通过 {s=$0} 被更新为当前行的内容。因此,{print s} 实际上打印的是上一行(即当前行之前的那一行)的内容。
{s=$0} 这部分在每行都会被执行,它将变量 s 更新为当前行的内容。
这个awk命令行是用来处理文本文件的,它主要用于数据处理和转换。命令解释如下:

NR>2:这是一个条件判断,表示从第三行(NR代表当前行号)开始执行后续操作。

print s:当满足条件 NR > 2 后,会打印变量 s 的值。但在执行此行之前,s 的默认值为空字符串(“”)。

s=$0:在这里,$0 表示当前行的所有内容,所以这一行将当前行的内容赋值给 s,并将 s 的值更新为下一行的内容。

整个命令的效果就是读取输入文件从第三行开始,每次处理一行并将该行内容累加到变量 s 中,直到文件结束。最后一行不会输出,因为它的 NR 不满足条件 NR>2。

读取第一行,NR=1,不执行print s,s=1

读取第二行,NR=2,不执行print s,s=2 (大于为真)

读取第三行,NR=3,执行print s,此时s是上一次p赋值内容2,s=3

最后一行,执行print s,打印倒数第二行,s=最后一行。

对于每一行输入(从 seq 5),{s=$0} 都会被执行,它将当前行的内容($0)赋值给变量 s。
但是,{print s} 只在 NR>2(即行号大于2)时执行。这意味着在处理前三行时(行号为1, 2, 3),{print s} 不会被执行,而 s 会在每次迭代时更新为当前行的内容。
当处理到第四行(行号为4)时,{print s} 开始执行,但此时 s 包含的是第三行的内容(即3),因为 {s=$0} 在 {print s} 之前执行,并且每次迭代都会更新 s。
因此,你会看到从第四行开始,每次迭代都会打印出上一行的内容,直到输入结束。
echo ‘hello world ftx’ | sed -E ‘s/hello ([^ ]) ([^ ])/\1 \2/’
echo ‘hello world ftx’ | sed -E ‘s/hello ([^ ]) ([^ ])/\2 \1/’

将a文件相同IP的服务名合并:

cat a

192.168.1.1: httpd httpd
192.168.1.1: tomcat httpd tomcat
192.168.1.2: httpd httpd
192.168.1.2: postfix httpd postfix
192.168.1.3: mysqld mysqld
192.168.1.4: httpd httpd

字符串拼接
当 AWK 遇到第一行数据时,它首先根据 BEGIN 块(如果存在)来设置初始参数,然后处理第一行。假设第一行的第一个字段是 “key1″,第二个字段是 “value1″,那么执行 {a[$1]=a[$1] $2} 时,a[“key1”] 将被初始化为 “value1″(因为 a[“key1”] 之前不存在,所以 a[$1] $2 实际上就是 “” “value1″,即 “value1″)。
当 AWK 遇到第二行数据时,如果第二个字段的索引(即第一个字段)仍然是 “key1″,那么 a[“key1”] 将被更新为 “value1value2″(假设第二行的第二个字段是 “value2″)。这里,a[$1] 已经存在(即 “value1″),所以 a[$1] $2 就是 “value1” “value2″,结果被赋值回 a[“key1”]。
如果第二行的索引是一个新的值(比如 “key2″),那么 a[“key2”] 将被初始化为该行的第二个字段的值。
数组a存储是$1=a[$1] $2,第一个a[$1]是以第一个字段为下标,值是a[$1] $2,也就是$1=a[$1] $2,值的a[$1]是用第一个字段为下标获取对应的值,但第一次数组a还没有元素,那么a[$1]是空值,此时数组存储是192.168.1.1=httpd,再遇到192.168.1.1时,a[$1]通过第一字段下标获得上次数组的httpd,把当前处理的行第二个字段放到上一次同下标的值后面,作为下标192.168.1.1的新值。此时数组存储是192.168.1.1=httpd tomcat。每次遇到相同的下标(第一个字段)就会获取上次这个下标对应的值与当前字段并作为此下标的新值
awk ‘BEGIN{FS=”:”;OFS=”:”}{a[$1]=a[$1] $2}END{for(v in a)print v,a[v]}’

192.168.1.1: httpd tomcat
192.168.1.2: httpd postfix
192.168.1.3: mysqld
192.168.1.4: httpd

2、两个文件差异对比

文件内容:

seq 1 5 > a

seq 3 7 > b

awk ‘FNR==NR{a[$0];next}{if($0 in a)print $0}’ a b

FNR==NR:这是一个条件判断。在awk中,FNR表示当前正在处理的文件中的记录号(行号),而NR表示自开始以来读取的记录总数。当awk正在处理第一个文件时,FNR和NR是相等的。因此,这个条件只在处理第一个文件时(这里是文件a)为真。
{a[$0];next}:当上述条件为真时,执行这个代码块。这里,$0代表当前行的内容。a[$0]将当前行的内容作为键存储在数组a中(注意,这里没有显式地给数组a的元素赋值,但在awk中,仅通过键名引用数组会自动创建该键,并将其值初始化为空字符串)。next语句指示awk跳过当前行的后续模式和处理,直接读取下一行。这意味着,当处理文件a时,awk会将每一行的内容添加到数组a中,并且不会执行{if($0 in a)print $0}这个代码块。
{if($0 in a)print $0}:当awk开始处理第二个文件(这里是文件b)时,上述FNR==NR条件不再为真,因此awk会执行这个代码块。这里,它检查当前行($0)是否作为键存在于数组a中(即检查文件b的当前行是否在文件a中出现过)。如果是,就打印出这行内容。
a b:这是awk命令的两个输入文件。首先处理a,然后处理b。

、将第一列合并到一行

cat file

1 2 3
4 5 6
7 8 9
awk ‘{for(i=1;i<=NF;i++) a[i]=a[i]$i” “;} END{for(v in a) print a[v]}’ file

解读:
for循环是遍历每行的字段,NF等于3,循环3次。
读取第一行时:
第一个字段:a[1]=a[1]1″ ” 值a[1]还未定义数组,下标也获取不到对应的值,所以为空,因此a[1]=1 。
第二个字段:a[2]=a[2]2″ ” 值a[2]数组a已经定义,但没有2这个下标,也获取不到对应的值,为空,因此a[2]=2 。
第三个字段:a[3]=a[3]3″ ” 值a[2]与上面一样,为空,a[3]=3 。
读取第二行时:
第一个字段:a[1]=a[1]4″ ” 值a[2]获取数组a的2为下标对应的值,上面已经有这个下标了,对应的值是1,因此a[1]=1 4
第二个字段:a[2]=a[2]5″ ” 同上,a[2]=2 5
第三个字段:a[3]=a[3]6″ ” 同上,a[2]=3 6
读取第三行时处理方式同上,数组最后还是三个下标,分别是1=1 4 7,2=2 5 8,3=36 9。最后for循环输出所有下标值。

awk ‘{
for(i=1; i<=NF; i++) {
if (i < NF) {
# 如果不是最后一个字段,则在值后面添加一个空格
a[i] = a[i] $i ” “
} else {
# 如果是最后一个字段,则不添加空格
a[i] = a[i] $i
}
}
}
END {
# 遍历并打印数组a的内容
for(i=1; i<=NF_seen; i++) { # 注意:这里假设NF_seen在之前被正确设置以记录最大字段数
if (a[i] != “”) { # 只打印那些非空的值(如果某些字段在某些行中不存在)
print a[i]
}
}
}
‘ file

------本页内容已结束,喜欢请分享------

感谢您的来访,获取更多精彩文章请收藏本站。

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容