awk命令笔记

news/2024/11/8 3:12:13/
awk 'BEGIN { commands } PATTERN { commands } END { commands }'begin块               body块                 end块
  1. begin/end区分大小写,大写有效。
  2. 空格可选。
  3. 内置变量需大写。

执行流程:
1)先执行begin块。
相当于循环初始化。
2)对每条输入记录,执行body块。
相当于执行循环体。
如果是处理多行文本,默认用换行符拆分记录,即循环每行进行处理。
3)对每条记录(每行文本)的默认处理:
用分隔符(默认是空格)分隔每行中的字段,分别赋值给$1, $2 … ($0代表整行)
根据需要对各个字段进行处理,输出等。
4)循环结束后,执行end块。

pattern模式:
1)/正则表达式/:/some string/
2)关系表达式:$2>10 NR%2==0
3)模式匹配表达式: ~ ~!
4)范围区间:
'NR==1, NR==10' 1-10行

$ cat /tmp/test.log 
2023-05-18 05:08:56.965846   460  4936 I SOMEIP  : 2023-05-18 05:08:56.871641 [info] [TID:571]  repetitionsBaseDelay_ = 100
2023-05-18 05:08:56.965863   460  4936 I SOMEIP  : 2023-05-18 05:08:56.871645 [info] [TID:571]  repetitionsMax_ = 3
2023-05-18 05:08:30.896556  1538  1538 I SettingsIFImpl: line 1
2023-05-18 05:08:30.896556  1538  1538 I SettingsIFImpl: line 2# 包含SOMEIP的行
$ awk '/SOMEIP/' /tmp/test.log
2023-05-18 05:08:56.965846   460  4936 I SOMEIP  : 2023-05-18 05:08:56.871641 [info] [TID:571]  repetitionsBaseDelay_ = 100
2023-05-18 05:08:56.965863   460  4936 I SOMEIP  : 2023-05-18 05:08:56.871645 [info] [TID:571]  repetitionsMax_ = 3# 不包含SOMEIP的行
$ awk '!/SOMEIP/' /tmp/test.log
2023-05-18 05:08:30.896556  1538  1538 I SettingsIFImpl: line 1
2023-05-18 05:08:30.896556  1538  1538 I SettingsIFImpl: line 2# 把字段$6匹配模式的行,打印每行中$6后续内容
$ awk 'BEGIN{ ORS=" " } $6~/SOMEIP/{ for(i=8; i<=NF; i++) { print $i } print "\n" }' /tmp/test.log
2023-05-18 05:08:56.871641 [info] [TID:571]  repetitionsBaseDelay_ = 100 2023-05-18 05:08:56.871645 [info] [TID:571]  repetitionsMax_ = 3 2023-05-18 05:08:56.871641 [info] [TID:571]  repetitionsBaseDelay_ = 100 2023-05-18 05:08:56.871645 [info] [TID:571]  repetitionsMax_ = 3 

内置变量

FILENAME: 当前文件名
NR: 表示所有处理文件已处理的输入记录个数
FNR: 文件的当前记录数
NF: 表示数据文件中数据字段的个数,可以通过$NF获取最后一个数据字段
ARGC: 命令行参数个数
ARGV: 命令行参数数组
$0: 这个变量包含执行过程中当前行的文本内容。
$n: 一行记录的第n个字段,例如$1, $2FS:输入字段分隔符
OFS:输出字段分隔符
RS:输入记录分割符
ORS:输出字段分隔符
FIELDWIDTHS:定义数据字段的宽度
$ awk '{print FILENAME, NF, $0}' /tmp/test.log 
/tmp/test.log 8 2023-05-18 05:08:30.896556  1538  1538 I SettingsIFImpl: line 1
/tmp/test.log 8 2023-05-18 05:08:30.896556  1538  1538 I SettingsIFImpl: line 2$ awk '{print FILENAME "line>>" NR, $0}' /tmp/test.log 
/tmp/test.logline>>1 2023-05-18 05:08:30.896556  1538  1538 I SettingsIFImpl: line 1
/tmp/test.logline>>2 2023-05-18 05:08:30.896556  1538  1538 I SettingsIFImpl: line 2

body块:

/pattern/ { commands }

1)匹配正则表达式pattern的记录,执行命令commands。
2)可以有多个匹配模式,例如:
(1)当匹配pattern1时,执行commands1。如果匹配pattern2就执行commands2.
(2)next作用就是跳过后面的模式匹配和命令(类似if/else的关系);如果没有next命令,则每个模式匹配都会进行判断。

/patten1/ {commands1; next} /pattern2/ {commands2}

3)如果省略{commands},默认执行print $0。只执行/pattern/匹配过滤。
(1)对于简单字符串,退化成grep。
(2)利用内置变量和表达式做复杂查找(筛选),例如筛选出偶数行。

$ awk '/Max/' /tmp/test.log 
$ awk 'NR%2==0' /tmp/test.log

4)print函数在commands中可以重定向输出到文件或者管道

awk 'NR%2==0 { print $1 > "/tmp/part.log" }' /tmp/test.log

各个命令块:
1)可编写多条语句。每行一个命令,结尾不必有分号。也可以分号分隔的多条命令。
2)支持if-else,for,while等控制结构。
3)支持数据,索引可用数字或字符串,相当于map。
4)可自定义函数
function find_min(num1, num2) { if (num1 < num2) return num1 return num2 }
5)内置函数:
(1)数学函数:sin, cos, log, sqrt, int, rand
(2)字符串函数:gsub, sub, substr, index, length, match, split, tolower, toupper, sprintf, strtonum
sub(reg, str [, target])
a) 匹配reg的字符串,替换为str。
b) target为替换目标字符串,默认为 0 ,可指定为某个表里或者字段 0,可指定为某个表里或者字段 0,可指定为某个表里或者字段n。
c) gsub和sub原型一样,替换所有匹配reg的字符串,sub只替换第一个出现。
gensub(reg, str, h [, target])
a) h可指定替换第几个出现的reg,或者“g/G”标识替换全部。
b) 在str中可以通过“\n”引用reg出现的位置。
print
(3)时间函数:mktime, strftime, systime
(4)位操作函数:and, or, xor, compl, lshift, rshift
(5)其他函数:close, flush, exit, delete, getline, next, nextfile, return system

# sub,gsub例子
# sub
$ cat /tmp/test.log 
2023-05-18 05:08:56.965846   460  4936 I SOMEIP  : 2023-05-18 05:08:56.871641 [info] [TID:571] client_timer_18215_1 repetitionsBaseDelay_ = 100
2023-05-18 05:08:56.965863   460  4936 I SOMEIP  : 2023-05-18 05:08:56.871645 [info] [TID:571] client_timer_18215_1 repetitionsMax_ = 3#sub函数只替换第一次出现的字符串
$ awk '{ sub(/2023-05-18/, "1234-56-78"); print $0 }' /tmp/test.log 
1234-56-78 05:08:56.965846   460  4936 I SOMEIP  : 2023-05-18 05:08:56.871641 [info] [TID:571] client_timer_18215_1 repetitionsBaseDelay_ = 100
1234-56-78 05:08:56.965863   460  4936 I SOMEIP  : 2023-05-18 05:08:56.871645 [info] [TID:571] client_timer_18215_1 repetitionsMax_ = 3#gsub函数替换一行中所有匹配的字符串
$ awk '{ gsub(/2023-05-18/, "1234-56-78"); print $0 }' /tmp/test.log 
1234-56-78 05:08:56.965846   460  4936 I SOMEIP  : 1234-56-78 05:08:56.871641 [info] [TID:571] client_timer_18215_1 repetitionsBaseDelay_ = 100
1234-56-78 05:08:56.965863   460  4936 I SOMEIP  : 1234-56-78 05:08:56.871645 [info] [TID:571] client_timer_18215_1 repetitionsMax_ = 3# gsub删除收尾空格
$ awk '{gsub(/^ +| +$/,"")} {print "=" $0 "="}' onefile.txt

用多个分隔符拆分记录:

$ cat test.log
2023-05-18 05:08:56.965846   460  4936 I SOMEIP# 用空格、.、:多个分隔符来拆分记录,默认只用空格分隔符
$ awk -F "[ .:]" '{print $1,$2,$3,$4,$5}' test.log 
2023-05-18 05 08 56 965846# FS和-F参数等效
$ awk 'BEGIN{FS="[ .:]"} {print $1,$2,$3,$4,$5}' test.log 
2023-05-18 05 08 56 965846

自定义变量
1)对脚本比较有用,命令行中用处不大。
2)在命令行中,自定义变量写在脚本指令之后。脚本指令紧挨着awk。

$ awk '{ print name"="age }' name=tom age=12 /tmp/test.log 
tom=12
tom=12

数组:
1)关联数组,map类型。
2)不用先定义
3)for…in循环可能无序,for (i=1…)循环有序

$ awk '
BEGIN {
str="this is a string"; 
len=split(str, array, " "); 
print length(array), len; 
for (i in array) print i": "array[i]; 
}'4 4
1: this
2: is
3: a
4: string$ awk 
'BEGIN {
str="this is a string"; 
len=split(str, array, " "); 
print length(array), len; 
for (i=1; i<=len; i++) print i": "array[i]; 
}'
4 4
1: this
2: is
3: a
4: string$ awk 
'BEGIN{ 
arr["one"]=1; 
arr["two"]=2; 
arr["three"]=3; for (item in arr) print item"->"arr[item] 
}'
three->3
two->2
one->1

流程控制:

$ cat /tmp/file.txt 
line 1
line 2
line 3
line 4
line 5
line 6# if
$ awk '{ 
if (NR % 2 == 0) 
{print $0
} 
else if (NR %3 == 0) 
{print $0
} 
}' /tmp/file.txt line 2
line 3
line 4
line 6# while 循环
$ awk 'BEGIN{ 
count=3; 
while (count>0) 
{print count; count--;
} 
}' /tmp/file.txt 
3
2
1# for循环
$ awk 'BEGIN{ 
for(count=3; count>0; count--) 
{print count;
} 
}' /tmp/file.txt 
3
2
1

控制命令:

break,退出while/for循环
continue,继续下一次循环
next,继续系一条记录,把body块作为循环体,next类似continue,跳到下一条记录。
exit, 在body块中exit,结束body块循环,执行END;在END中exit,退出程序。包body块作为循环体,exit类似break。

数值计算例子:


$ cat /tmp/num.txt
1
2
3
4
5
# 计算均值
$ awk 'BEGIN{ sum=0; } { sum+=$1; } END{ print sum/NR }' /tmp/num.txt 
3$ cat /tmp/num.txt
1 2 3 4 5
11 22 33 44 55
10 20 30 40 50
# 计算均值
$ awk '{ sum=0; for(i=1; i<=NF; i++) sum+=$i; print sum/NF }' /tmp/num.txt 
3
33
30

awk可以自定义函数,暂时用不到,先不记录了。


http://www.ppmy.cn/news/241142.html

相关文章

无领导面试:如何运用这5种题型回答问题?

无领导面试考察需具备自我认知、情感管理、团队协作、沟通表达、学习能力等多方面的素养&#xff0c;这种银行无领导面试的方式将逐渐成为趋势&#xff0c;今天小编就给大家来说说无领导面试有哪些题型以及如何运用回答。从如信银行考试中心了解到&#xff1a; 一、常见的无领导…

Android Bluetooth(蓝牙) - 概念和框架

目录 基本概念: 蓝牙的总体流程图 参考文献: 基本概念: RF(RADIO):射频层,本地蓝牙数据通过射频发送给远端设备,并且通过射频接收自远端蓝牙设备的数据BB(BASEBAND):基带层,进行射频信号与数字或语音信号的相互转化,实现基带协议和其它的底层连接规程。LMP(LINK …

内存分配方式以及它们的区别

从静态存储区域分配 内存在程序编译的时候就已经分配好&#xff0c;这块内存在程序的整个运行期间都存在。例如全局变量&#xff0c;static 变量。 在栈上创建 在执行函数时&#xff0c;函数内局部变量的存储单元都可以在栈上创建&#xff0c;函数执行结束时这些存储单元自…

内存分配器初步了解

内存分配器初步了解 这片文章对于内存分配器的实现总结的非常好&#xff0c;忍不住记录下来&#xff0c;归纳一二。 自己动手实现一个malloc内存分配器 1. 我们什么时候知道程序到底需要多少内存&#xff1a;只有当程序运行起来我们才能知道 2. 内存分配2个关键问题&#xf…

exfat默认配置大小_U盘exFAT格式分配单元大小选多少合适?

U盘一般有三种常见的格式&#xff1a;FAT32&#xff0c;NTFS和exFAT。 现在超过4GB的U盘格式化时默认是NTFS分区&#xff0c;但是这种格式是很伤U盘的&#xff0c;因为NTFS分区是采用“日志式”的文件系统&#xff0c;需要记录详细的读写操作&#xff0c;肯定会比较伤闪盘芯片&…

学计算机u盘多少g合适,U盘设定分配单元的大小多少合适

原标题&#xff1a;"巧妙为U盘设定分配单元的大小"相关电脑问题教程分享。 - 来源:网络投稿。 使用Win7系统的朋友&#xff0c;在对U盘格式化的时候&#xff0c;有没有发现&#xff0c;可以设定分配单元的大小。分配单元大小&#xff0c;可以对U盘分成若干块存储空间…

C++实现简单的固定大小内存分配器

背景介绍 最近在了解性能优化相关的知识&#xff0c;了解到内存分配是一个可优化性能的方向&#xff0c;在相关书籍中看到一个固定大小的内存分配器实现&#xff0c;觉得挺有意思的&#xff0c;这里跟大家分享&#xff0c; 据说比通用的内存分配malloc()性能有不少提升。 源码…

exfat默认配置大小_如何分配U盘exFAT格式单元大小保证速度和空间呢

exFAT是一种专门针对移动存储设备的格式化格式&#xff0c;支持单个大于4GB的文件的操作&#xff0c;对于分配单元大小可以简单的说分配的单元的数值越大读写越快&#xff0c;但是存储空间会浪费。 这 里解释一下“分配单元大小”的含义。所谓分配单元大小&#xff0c;即是系统…