awk详细教程-基础篇_awk教程_surpassLiang的博客-程序员宅基地

技术标签: 行处理工具  AWK  linux  正则表达式  技巧  Linux命令  

1.前言

awk是Unix环境下一个强大的文本分析工具,相对于grep和sed,awk在其对数据分析并生成报告时,显得尤为强大。它还有许多精心设计的特性,支持awk脚本语言执行,从而极大程度提高重用率。其功能就是把文件默认逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。这里之所以说默认,是因为这里也是有配置项进行修改的。

2.环境准备

这里主要准备一个文本文件,名称建议为awk.txt,内容如下:

1 this is a test
2 Are you like awk
3 This's a awk
4 There are orange,apple,mongo
I like awk

2.语法形式

awk [选项参数] 'script' var=value [file(s)/管道流]
awk [选项参数] -f scriptfile var=value [file(s)/管道流]

2.1 选项参数

在awk工具中,选项参数有很多,这里常用的参数如下:

2.1.1 -f scripfile or --file scriptfile

从脚本文件中读取awk命令。建议:针对于简单的awk命令,直接在命令行书写即可,如果是较为复杂而且常用的功能,建议编写awk脚本语言,便于后期重复利用。

准备awk脚本文件awk.awk,内容如下:

{print "hello"}

执行如下命令:

awk -f awk.awk awk.txt

执行结果如下:

在上图中,我们先查看脚本文件awk.awk和文本文件awk.txt两个文件的内容,下面是输出结果。大家可以想一下为什么这里输出5个hello?

2.1.2 -F fs or --field-separator fs

指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。

这里需要注意以下两点:

1)分隔符是支持正则表达式的;

2)这个参数和内置变量FS是等效的(关于内置变量我们后面会说到)。

针对上面的文本的例子,我们按照字母i和逗号作为分隔符,进行分解,代码如下:

#当前记录的第n个字段,字段间由FS分隔
awk -F "[i,]" '{print $1"=="$2"=="$3"=="$4}' awk.txt

针对于上面输出的结果,大家感兴趣可以自行分析一下。

2.1.3 -v var=value or --asign var=value

赋值一个用户定义变量,如果是需要多个变量,则需要使用多个-v.

下面的例子是我们输出两列行号,一列从3开始,一列从13开始:

#$0表示输出一整行
awk -v a=3 -v b=13 '{print a++,b++,$0}' awk.txt

2.2 处理文本

在AWK工具中,处理的文本来源主要包括文本和管道输入流,其中文本包括支持多个文本。

1)文件处理

awk '{print $0}' 1.txt 2.txt

2)管道输入

ll|awk '{print $0}'

3.运算符

运算符 描述
= += -= *= /= %= ^= **= 赋值
?: C条件表达式
|| 逻辑或
&& 逻辑与
~ 和 !~ 匹配正则表达式和不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接
+ - 加,减
* / % 乘,除与求余
+ - ! 一元加,减和逻辑非
^ *** 求幂
++ -- 增加或减少,作为前缀或后缀
$ 字段引用
in 数组成员

这里我们简单举几个例子,感兴趣的可以各自尝试一下:

# 1)提取第一列为1的行
awk '$1==1{print $0}' awk.txt
# 2)提取第一列为1或者3的行
awk '$1==1 || $1==3{print $0}' awk.txt
# 3)提取第一列不为数字的行
awk '$1 !~ /[0-9]/{print $0}' awk.txt

4. 内置变量

变量 描述
$n 当前记录的第n个字段,字段间由FS分隔
$0 完整的输入记录
ARGC 命令行参数的数目
ARGIND 命令行中当前文件的位置(从0开始算)
ARGV 包含命令行参数的数组
CONVFMT 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO 最后一个系统错误的描述
FIELDWIDTHS 字段宽度列表(用空格键分隔)
FILENAME 当前文件名
FNR 各文件分别计数的行号
FS 字段分隔符(默认是任何空格)
IGNORECASE 如果为真,则进行忽略大小写的匹配
NF 一条记录的字段的数目
NR 已经读出的记录数,就是行号,从1开始
OFMT 数字的输出格式(默认值是%.6g)
OFS 输出字段分隔符,默认值与输入字段分隔符一致。
ORS 输出记录分隔符(默认值是一个换行符)
RLENGTH 由match函数所匹配的字符串的长度
RS 记录分隔符(默认是一个换行符)
RSTART 由match函数所匹配的字符串的第一个位置
SUBSEP 数组下标分隔符(默认值是/034)

这里大部分内置变量都很容易理解,不知道大家是否还记得前面针对AWK的描述中提到"文件默认逐行的读入,以空格为默认分隔符将每行切片",既然是默认,一定有修改的地方;针对于“以空格为默认分隔符将每行切片”,前面已经提到过可以通过参数-F进行设置,当然也可以通过内置变量FS设置,对于“文件默认逐行的读入”,可以通过RS设置有意思的是输出的分隔符符合分行的设置可以通过OFS和ORS设置。下面我们就这四个命令做以举例,其他的大家可以自行尝试。

变量的设置可以通过两种方式:1)通过参数-v进行设置,一种是通过awk命令进行设置。我们通过一个例子将这两种都演示一遍。在这里,输入的变量我们通过-v设置,输出的变量我们通过命令设置。

1)创建一个文本:

name=zhangsan,age=18,address=hebei

2)针对上述文本,我们以","为记录分隔符(即行分隔符,默认为回车),以“=”为字段分隔符(默认为空格),解析脚本。最终输出,我们以"&&"为行分隔符,以“:”为列分隔符,具体脚本如下:

#关于BEGIN的用法,后面会说道,这里只要知道这个指令是在解析文本之前只执行一次即可
awk -v FS="=" -v RS="," 'BEGIN{OFS=":";ORS="&&"}{print $1,$2}' awk2.txt

3)输出结果

其他情况大家可以自行增删改相关参数即可。

5.内置函数

5.1 算数函数

文本处理工具,对于数字的处理还是用处不大的,所以用处倒不是很大,感兴趣的可以了解一下

函数名 说明
srand( [Expr] ) 将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。返回先前的种子值。
sqrt( x ) 返回 x 平方根。
sin( x ) 返回 x 的正弦;x 是弧度。
rand( ) 返回任意数字 n,其中 0 <= n < 1。
log( x ) 返回 x 的自然对数。
int( x ) 返回 x 的截断至整数的值。
exp( x ) 返回 x 幂函数。
cos( x ) 返回 x 的余弦;x 是弧度。
atan2( y, x ) 返回 y/x 的反正切。

5.2 字符串函数

这里的函数就非常有使用价值了,毕竟这是文本处理工具嘛。

函数 说明
gsub( Ere, Repl, [ In ] ) gsub 是全局替换( global substitution )的缩写。除了正则表达式所有具体值被替代这点,它和 sub 函数完全一样地执行。
sub(regex,sub,string) sub 函数执行一次子串替换。它将第一次出现的子串用 regex 替换。第三个参数是可选的,默认为 $0。
substr(str, start, l) substr 函数返回 str 字符串中从第 start 个字符开始长度为 l 的子串。如果没有指定 l 的值,返回 str 从第 start 个字符开始的后缀子串。
index( String1, String2 ) 在由 String1 参数指定的字符串(其中有出现 String2 指定的参数)中,返回位置,从 1 开始编号。如果 String2 参数不在 String1 参数中出现,则返回 0(零)。
length [(String)] 返回 String 参数指定的字符串的长度(字符形式)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。
blength [(String)] 返回 String 参数指定的字符串的长度(以字节为单位)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。
substr( String, M, [ N ] ) 返回具有 N 参数指定的字符数量子串。子串从 String 参数指定的字符串取得,其字符以 M 参数指定的位置开始。M 参数指定为将 String 参数中的第一个字符作为编号 1。如果未指定 N 参数,则子串的长度将是 M 参数指定的位置到 String 参数的末尾 的长度。
match( String, Ere ) 在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式出现在其中)中返回位置(字符形式),从 1 开始编号,或如果 Ere 参数不出现,则返回 0(零)。RSTART 特殊变量设置为返回值。RLENGTH 特殊变量设置为匹配的字符串的长度,或如果未找到任何匹配,则设置为 -1(负一)。
split( String, A, [Ere] ) 将 String 参数指定的参数分割为数组元素 A[1], A[2], . . ., A[n],并返回 n 变量的值。此分隔可以通过 Ere 参数指定的扩展正则表达式进行,或用当前字段分隔符(FS 特殊变量)来进行(如果没有给出 Ere 参数)。除非上下文指明特定的元素还应具有一个数字值,否则 A 数组中的元素用字符串值来创建。
tolower( String ) 返回 String 参数指定的字符串,字符串中每个大写字符将更改为小写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。
toupper( String ) 返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。
sprintf(Format, Expr, Expr, . . . ) 根据 Format 参数指定的 printf 子例程格式字符串来格式化 Expr 参数指定的表达式并返回最后生成的字符串。
strtonum(str) strtonum 将字符串 str 转换为数值。 如果字符串以 0 开始,则将其当作十进制数;如果字符串以 0x 或 0X 开始,则将其当作十六进制数;否则,将其当作浮点数。

1)gsub、sub 使用

#gsub使用
awk 'BEGIN{info="今天是2021年4月4日";gsub(/[0-9]+/,"**",info);print info}'
#输出:今天是**年**月**日
#----------------------
#sub使用
awk 'BEGIN{info="今天是2021年4月4日";sub(/[0-9]+/,"**",info);print info}'
#输出:今天是**年4月4日

2)截取字符串(substr使用)

awk 'BEGIN{info="今天date是2021年4月4日";print substr(info,4,10);}'
#输出:ate是2021年4

3)格式化字符串输出(sprintf使用)

格式符 说明
%d 十进制有符号整数
%u 十进制无符号整数
%f 浮点数
%s 字符串
%c 单个字符
%p 指针的值
%e 指数形式的浮点数
%x %X 无符号以十六进制表示的整数
%o 无符号以八进制表示的整数
%g 自动选择合适的表示法
awk 'BEGIN{info=sprintf("%s今年%d岁","小明",26);print(info)}'

5.3 日期函数

函数名 说明
mktime( YYYY MM DD HH MM SS[ DST]) 生成时间格式
strftime([format [, timestamp]]) 格式化时间输出,将时间戳转为时间字符串
systime() 得到时间戳,返回从1970年1月1日开始到当前时间(不计闰年)的整秒数

5.4 其他函数

system 执行特定的命令然后返回其退出状态。返回值为 0 表示命令执行成功;非 0 表示命令执行失败。

我觉得这个函数是最重要的函数,这个也是我学习这个工具的一个强大动力,他的威力在于可以可以调用linux系统命令。

5.4.1 实例1

现在我要创建文件名为1-20的文件夹:

1)创建一个文本文件createfile.txt,1-20编号;

2)注意这里使用逗号隔开的,所以我们的命令如下:

awk -v RS="," '{system("mkdir "$1)}' createfile.txt

5.4.2 实例2 

删除章节5.4.1创建的文件夹。这里我们通过ll命令的方式删除。

1)首先我们执行ll命令:

2)输入命令

ll |awk 'NR!=1 && $9 ~ /^[0-9]{1,2}$/{system("rm -rf "$9)}'

注意:

        $9 ~ //这里是包含的意思,所以在正则表达式中必须加上“^”以...开始的符号和“$”以...结尾的符号。

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/oYinHeZhiGuang/article/details/115482821

智能推荐

反转字符串 (利用C指针)_c++指针实现字符串反转_Sivan_Xin的博客-程序员宅基地

代码实现:#include <stdio.h>#include<stdlib.h>#include <string.h>void swap(char* p1, char* p2); void reverse(char* start, char* end);int main() { char a[] = {"Hello"}; int len = strlen(a)-1; //从第四个数开始,strlen=5. reverse(&a_c++指针实现字符串反转

数据库系统概论(第一章绪论)-程序员宅基地

第一章 绪论1.1 数据库系统概述4个基本概念:数据、数据库、数据库管理系统、数据库系统数据:描述事物的符号记录 数据库:数据库是长期储存在计算机内、有组织的、可共享的大量数据的集合(永久存储、有组织、可共享) 1、数据库中的数据按一定的数据模型组织、描述和存储; 2、可共享 3、具有较小的冗余度 4、较高的数据独立性和易扩展性 数据库管理系统:使位于用户与...

基于TT 双WAN固件(dualwan)下的QOS脚本 很给力_douwle wan 刷tt-程序员宅基地

脚本关键参数说明(V4.0):IPS:限速开始IP地址IPE:限速结束IP地址IPS和IPE最好不要填写2---254,不然脚本运行时间会比较长,会多占用一些内存。效率上,如果采用了u32 hash(v4.0和智能QOS修改版本)就没影响。UP=35:总上传带宽。我的ADSL虽然是50KB/S,但为了低延迟,还是填35吧DOWN=575:总下载带宽。我的ADSL虽然能达到6_douwle wan 刷tt

进程注入之进程提权_WgpSec狼组安全团队的博客-程序员宅基地

本文作者:Gality本文字数:7928字阅读时长:20分钟本文属于【狼组安全社区】原创奖励计划,未经许可禁止转载由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,狼组安全团队以及文章作者不为此承担任何责任。狼组安全团队有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经狼组安全团队允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。最近在研究进程注入相关的东西,主要是参考process-_进程提权

PriorityQueue PriorityBlockingQueue 优先级队列与优先级阻塞队列 源码解析_priorityqueue priorityblockqueue-程序员宅基地

试想一下,如果要在一堆数据中找出最大的或者最小的是不要进行一次遍历,时间复杂度为O(N)还能不能优化,比如O(1)的时间复杂度就能获取到。这就是这篇博客需要说的PriorityQueue优先级队列。先看结构完全二叉树:一棵有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,节点得插入永远在下一个位置。下面得紫色的那排小字就是节点的序号。那么第N个元素的左孩子queue [2 * n + 1]右孩子就是queue [2 *(n + 1)]。看到源码就会发现PriorityQueue存储_priorityqueue priorityblockqueue

《Best Practices for Data-Efficient Modeling in NLG:How to Train Production-Ready Neural Models with_bucket data训练策略-程序员宅基地

标题:《Best Practices for Data-Efficient Modeling in NLG:How to Train Production-Ready Neural Models with Less Data》作者:Facebook时间:2020项目地址:https://github.com/facebookresearch/DataEfficientNLG(只是个数据集仓库,暂时还没有开放code)中文:数据高效建模的最佳实践NLG:如何用较少的数据训练可落地的神经网络模型简介_bucket data训练策略

随便推点

辗转相除法,递归求解最大公约数和最小公倍数_编写辗转相除法求最大公约数的递归函数-程序员宅基地

最大公约数#include<stdio.h>int gcd(int,int);int main(){ int m,n; scanf("%d %d",&m,&n); printf("%d\n",gcd(m,n)); return 0; } int gcd(int m,int n){ int c; while(n) { c=m%n; m=n; n=c; } return m;}设计辗转相除法函数求解#includ..._编写辗转相除法求最大公约数的递归函数

Maven项目中Mybatis环境搭建_maven mybatis-程序员宅基地

Mybatis简介mybatis是一款流行的,优秀的,基于Java的持久层框架,它内部封装了JDBC,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。采用 _maven mybatis

C语言用数组实现十个国家名字按字典排序_c语言国家名称排序-程序员宅基地

试题描述输入10个国名,编程按字典顺序输出国名。请使用数组实现。输入输入包含十行,每行为一个国名,长度均不超过20。输出按字典顺序输出国名,每行为一个国名。输入示例SlovakChinaJapanEnglandSwedenLithuaniaMonacoCroatiaMaltaLuxembourg输出示例ChinaCroatiaEnglandJapanLithuaniaLuxembourgMaltaMonacoSlovakSweden_c语言国家名称排序

ARP攻击dns攻击_arpspoot查看网关-程序员宅基地

ARP断网攻击、dns欺骗_arpspoot查看网关

WIN10上映射的网络服务器怎么删除,win10系统下如何使用Registry断开映射的网络驱动器...-程序员宅基地

win10系统下如何使用Registry断开映射的网络驱动器如果您不再需要访问映射的网络驱动器,请使用以下步骤在Windows 10上正确断开连接。在Windows 10上,映射驱动器的功能允许您快速访问存储在连接到网络的其他设备上的文件。但是,您可能需要删除已映射的网络驱动器,因为您不再需要它,网络中的设置正在更改,或断开连接并重新连接以解决映射问题。无论原因是什么,Windows 10都包含映..._断开连接的网络驱动器怎么删除