awk详解「建议收藏」

awk详解「建议收藏」awk是linux中处理文本的强大工具,或者说是一种专门处理字符串的语言,它有自己的编码格式。awk的强大之处还在于能生成强大的格式化报告。awk的命令格式如下:其中常用选项有-F、-f等选项,后面会介绍。例如>awk-F:'{print$1}’file表示把file文件中每行数据以“:”分割后,打印出第一个字段。下面详细介绍使用方式。以下示例如不做…

大家好,又见面了,我是你们的朋友全栈君。

awk是linux中处理文本的强大工具,或者说是一种专门处理字符串的语言,它有自己的编码格式。awk的强大之处还在于能生成强大的格式化报告。
awk的命令格式如下:
这里写图片描述
其中常用选项有 -F、-f等选项,后面会介绍。
例如

>awk -F: '{print $1}' file

表示把file文件中每行数据以“:”分割后,打印出第一个字段。下面详细介绍使用方式。
以下示例如不做说明,均用file文件为例,file文件中数据为:

The dog:There is a big dog and a little dog in the park
The cat:There is a big cat and a little cat in the park
The tiger:There is a big tiger and a litle tiger in the park

一、数据字段变量

awk把分割后的数据字段自动分配给数据字段变量

  • $0表示整行文本
  • $1表示文本行中第一个数据字段
  • $2表示文本行中第二个数据字段
  • $n表示文本行中第n个数据字段
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{print $2}' file
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park

通过选项-F指定“:”为字段分隔符,把每行数据分为两段,然后输出第二个数据字段$2。

awk  '{print $2}' file

如不显示指定字段分隔符,awk的默认字段分隔符为任意空白字符,包括制表符、空格符、换行符等。

二、在脚本中使用多个命令

上一个示例在program命令脚本中只使用了一个print命令,如果使用多个命令,则在每个命令之间加分号。

root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{$1="Description:"; print $0}' file
Description: There is a big dog and a little dog in the park
Description: There is a big cat and a little cat in the park
Description: There is a big tiger and a litle tiger in the park

用冒号进行分割字段,然后把第一个字段替换为“Description:”,最后打印出整行数据。

三、从文件中读程序命令

如果program程序命令过多,可以单独放在一个文件中,然后从文件中读命令。还是以上面为例,把

{
$1="Description:"
print $0
}

单独放在一个文件script1中。再用awk处理脚本时,需要用选项 -f 指定脚本程序的位置。

root@lzj-virtual-machine:/home/lzj/demo# awk -F: -f script1 file
Description: There is a big dog and a little dog in the park
Description: There is a big cat and a little cat in the park
Description: There is a big tiger and a litle tiger in the park

四、在处理数据之前运行脚本

awk默认每次读入一行数据,然后用脚本进行处理。如果想在处理文本之前预处理一些命令,可以用BEGIN关键字指定。

root@lzj-virtual-machine:/home/lzj/demo# awk -F: 'BEGIN{print "开始处理..."}{print $2}' file
开始处理...
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park

五、在处理数据后运行脚本

用END关键字在处理完所有数据后,再运行善后处理工作。

root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{print $2} END{print "处理结束..."}' file
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park
处理结束...

六、在program中使用变量

变量又分为两种形式:awk内置的变量;用户自定义的变量。
【1】、内置变量
1. 与记录分隔符相关变量
– FS :输入字段分隔符
– OFS:输出字段分隔符
– RS:输入记录分割符
– ORS:输出字段分隔符
– FIELDWIDTHS:定义数据字段的宽度

FS用法

root@lzj-virtual-machine:/home/lzj/demo# awk 'BEGIN{FS=":"} {print $1, $2}' file
The dog There is a big dog and a little dog in the park
The cat There is a big cat and a little cat in the park
The tiger There is a big tiger and a litle tiger in the park

用FS指定字段分隔符为“:”,然后用“:”把每行数据分割为两段。

OFS用法
前面例子没有指定OFS,输出时默认数据字段之间用空格分开。

root@lzj-virtual-machine:/home/lzj/demo# awk 'BEGIN{FS=":"; OFS=">"} {print $1, $2}' file
The dog>There is a big dog and a little dog in the park
The cat>There is a big cat and a little cat in the park
The tiger>There is a big tiger and a litle tiger in the park

用FS指定输入字段分隔符“:”后,每行数据分为两个数据段,输出时,用OFS指定两个数据字段用“>”拼接。

RS和ORS用法
默认情况下RS和ORS设置为“\n”,表示输入数据流中的每一行作为一条记录,输出时每条记录之间也以“\n”进行分割。
下面以file2文件为例,fiel2文件中内容如下:

Tom is a student
and he is 20 years old

Bob is a teacher
and he is 40 years old

默认情况下,每行作为一条记录处理,但此种情况下,要把第一行和第二行作为一条记录处理,第三行和第四行作为一条记录处理。

root@lzj-virtual-machine:/home/lzj/demo# awk 'BEGIN{RS=""; ORS="\n"; FS="and"; OFS=","} {print $1, $2}' file2
Tom is a student
, he is 20 years old
Bob is a teacher
, he is 40 years old

2、与数据分割段有关的变量

ARGC    命令行参数个数
ARGV    命令行参数数组
FILENAME    当前输入文件的名字
IGNORECASE  如果为真,则进行忽略大小写的匹配
ARGIND  当前被处理文件的ARGV标志符
CONVFMT 数字转换格式 %.6g
ENVIRON UNIX环境变量
ERRNO   UNIX系统错误消息
FIELDWIDTHS 输入字段宽度的空白分隔字符串
FNR 文件的当前记录数
NR 已处理的输入记录数
NF 数据文件中数据字段的个数
OFMT    数字的输出格式 %.6g
RSTART  被匹配函数匹配的字符串首
RLENGTH 被匹配函数匹配的字符串长度

下面介绍几个常用的
ARGC和ARGV
ARGC表示命令行中的参数个数,ARGV是参数数组

root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{print ARGC, ARGV[0], ARGV[1]}' file
2 awk file
2 awk file
2 awk file

可见,每处理一行数据时,都是两个参数,第一个是awk本身,第二个是处理的文件名

NF
NF表示数据文件中数据字段的个数,可以通过$NF获取最后一个数据字段

root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{print NF, $NF}' file
2 There is a big dog and a little dog in the park
2 There is a big cat and a little cat in the park
2 There is a big tiger and a litle tiger in the park

每行记录数据通过“:”分割都有两个数据字段。

NR和FNR
FNR表示处理文件的当前记录号,NR表示所有处理文件已处理的输入记录个数。

root@lzj-virtual-machine:/home/lzj/demo# awk -F: '{print "NR="NR, "FNR="FNR, $2}' file file1
NR=1 FNR=1 There is a big dog and a little dog in the park
NR=2 FNR=2 There is a big cat and a little cat in the park
NR=3 FNR=3 There is a big tiger and a litle tiger in the park
NR=4 FNR=1 There is a big dog and a little dog in the forest
NR=5 FNR=2 There is a big cat and a little cat in the forest
NR=6 FNR=3 There is a big tiger and a litle tiger in the forest

注意,不要对NR和FNR加$,例如,如果对NR加$,加入NR等于5,实际就是取每条记录的第5个数据字段,实际没有这么多,只能取到空。

【2】、用户自定义变量
1、在脚本中使用用户自定义变量
建立一个script1的脚本,内容如下:

awk '
BEGIN{
    FS = ":"
    name = "lzj>"
}
{
    $1 = name
    print $0
}' file

运行该脚本 ./script

root@lzj-virtual-machine:/home/lzj/demo# ./script1
lzj> There is a big dog and a little dog in the park
lzj> There is a big cat and a little cat in the park
lzj> There is a big tiger and a litle tiger in the park

在脚本中直接定义了一个name变量,在脚本程序中可以直接引用该变量。注意在shell命令中,赋值语句“=”的前后是不能有空格的,但是在awk程序的内部是可以有的,因为awk是一种单独的编程语言。

2、在命令行中使用变量
首先定义一个script2脚本,其内容为:

BEGIN{
FS = ":"
}
{
    print $n
}

脚本中有一个n的变量,在命令行中传入

root@lzj-virtual-machine:/home/lzj/demo# awk -f script2 n=2 file
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park

注意一个问题:在命令行中传入的参数,默认在BEGIN是不能获取的,例如
script2脚本改为如下,在BEGIN部分获取n的值:

BEGIN{
FS = ":"
print "请输出第二部分...", n
}
{
    print $n
}
root@lzj-virtual-machine:/home/lzj/demo# awk -f script2 n=2 file
请输出第二部分... 
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park

运行命令,发现BEGIN部分的n值并没有打印出来。
但是如果用-v选项指定,并且把变量放在脚本代码之前,在BEGIN部分就可以访问了

root@lzj-virtual-machine:/home/lzj/demo# awk -v n=2 -f script2 file
请输出第二部分... 2
There is a big dog and a little dog in the park
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park

可以看到在BEGIN部分访问到了n的值2

七、在脚本中使用数组

1、数组赋值与查询
awk脚本中的数组有两种使用方式,一种是像其它高级语言一样,用数字下标来索引;另一种是用字典的key值来索引,key必须唯一。
新建script3脚本,内容为:

awk '
BEGIN{ arr["dog"] = "DOG" arr["cat"] = "CAT" print arr["cat"] }' file
root@lzj-virtual-machine:/home/lzj/demo# ./script3 
CAT

2、数组递归
新建脚本script4,内容为:

echo "hello" | awk '
BEGIN{
    arr["a"] = "A"
    arr["b"] = "B"
    arr["c"] = "C"
}
{
    for(var in arr)
    {
        print arr[var]
    }
}'

运行该脚本

root@lzj-virtual-machine:/home/lzj/demo# ./script4 
A
B
C

注意,有时数组的顺序是不一致的。
3、删除数组元素
修改script4脚本,增加delete语句

echo "hello" | awk '
BEGIN{ arr["a"] = "A" arr["b"] = "B" arr["c"] = "C" } { delete arr["c"] for(var in arr) { print arr[var] } }'

运行脚本

root@lzj-virtual-machine:/home/lzj/demo# ./script4 
A
B

可见删除了C元素。

八、脚本中使用正则匹配模式

在脚本中用正则匹配数据行时,正则表达式一定要放在脚本命令的左大括号之前,例如

$awk 'BEGIN{FS = ":"} /dog/{print $2}' file

匹配所有数据行中带dog字符的。

1、用~匹配特定数据字段
用正则表达式匹配指定的数据字段,匹配成功的,就是脚本要处理的数据。

root@lzj-virtual-machine:/home/lzj/demo# awk -F: '$1 ~ /^The cat$/{print $2}' file
There is a big cat and a little cat in the park

数据行中的第一个数据字段满足以The开头,cat结尾的数据行,执行后面的脚本。示例可知只有一条数据行满足记录。

当然也可以通过匹配的否定形式(!~)来排除数据行

root@lzj-virtual-machine:/home/lzj/demo# awk -F: '$1 !~ /dog/{print $2}' file
There is a big cat and a little cat in the park
There is a big tiger and a litle tiger in the park

2、使用数学表达式
可以在匹配数据行时用数学表达式。
以处理file3文件为例,文件内容为:

1:This is 1 line
2:This is 2 line
3:This is 3 line
4:This is 4 line
root@lzj-virtual-machine:/home/lzj/demo# awk -F: '$1 % 2 == 0{print $2}' file3
This is 2 line
This is 4 line

匹配第一个数据字段除2余0的数据行记录。
数学表达式中的+、-、*、/、^(平方)等都可以应用。
另外数学表达式不仅可以用在匹配部分,还可以用在BEGIN、program命令脚本、END部分。
常用的数学比较大小的表达式如下:
这里写图片描述

注意,如果要比较文本的话,只能用“==”进行比较

root@lzj-virtual-machine:/home/lzj/demo# awk -F: '$1 == "The cat"{print $2}' file
There is a big cat and a little cat in the park

九、awk中使用结构化命令

1、if结构
格式为:

if(condition){
    statement1
    statement2
    .....
}else
{
    statement3
    ......  
}

新建script5脚本,如果,每个数据行包括两个数据字段就执行if条件。

awk -F: '{ if(NF == 2) { print $1 print $2 }else { pring NF } }' file

运行脚本

root@lzj-virtual-machine:/home/lzj/demo# ./script5 
The dog
There is a big dog and a little dog in the park
The cat
There is a big cat and a little cat in the park
The tiger
There is a big tiger and a litle tiger in the park

2、while循环结构
格式

while(condition)
{
    statement1
    statement2
    ... 
}

新建script6脚本,计算10以内的奇数和

echo "hello" | awk '
{
    total = 0
    i = 1
    while(i < 10)
    {
        if(i % 2 == 0)
        {
            i++
            continue
        }
        total = total + i
        i++
    }
    print "total=", total
}'

运行脚本

root@lzj-virtual-machine:/home/lzj/demo# ./script6
total= 45

3、for循环
结构

for(variable addignment; condition; iteration peocess)
{
    statement1
    statement2
    ...
}

修改上一示例,改为for循环结构,求10以内奇数的和

echo "hello" | awk '
{
    total = 0
    for(i=1; i<10; i++)
    {
        if(i % 2 == 0)
        {
            continue
        }
        total = total + i
    }
    print "total=", total
}'

结果与上一示例相同。
注意:在awk的for和while循环中也支持breake、continue。

十、awk内置函数

数学函数
这里写图片描述

字符串函数
这里写图片描述

位操作函数
这里写图片描述

时间函数
这里写图片描述

十一、用户自定义函数

用户自定义函数一定要放在调用之前进行定义
格式

function function_name([variable])
{ statement1 statement2 .... }

例如处理file4文件,内容如下,只提取其中姓名和电话

Bob NanjingRoad 6623432
Terry BeijingRoad 6689764
Lily GuangzRoad 6623678

新建脚本script7,内容如下

awk '
function fshow() 
{
    printf "%-5s : %s\n", $1, $3
}
BEGIN{
    print "开始处理..."
}
{
    fshow() 
}' file4

运行脚本如下

root@lzj-virtual-machine:/home/lzj/demo# ./script7 
开始处理...
Bob   : 6623432
Terry : 6689764
Lily  : 6623678

注意:
printf的用法通C语言一样;
在脚本中BEGIN后面一定要紧跟“{”,否则会出错。

参考:linux脚本教程宝典

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/157379.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • IDEA打包jar包详尽流程

    IDEA打包jar包详尽流程打包流程1.打开菜单栏File-ProjectStructure2.点击Artifacts3.点击”+”-JAR-Frommodulewithdepenencies4.后弹出如下界面,自此开始,各种问题就来了首先Module中,我SocketDemo的Module含有SocketDemo、SocketDe…

  • pycharm专业版激活码(JetBrains全家桶)

    (pycharm专业版激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html9ZHRNTE33T-eyJsaWNlbnNlSWQi…

  • cshtml折叠

    cshtml折叠折叠效果折叠代码//#region说明functionmyfunction(){}//#endregion

  • GoLand-2021.4.14激活码_通用破解码

    GoLand-2021.4.14激活码_通用破解码,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • linux系统dpkg命令[通俗易懂]

    linux系统dpkg命令[通俗易懂]dpkg是Debianpackage的简写,为”Debian“操作系统专门开发的套件管理系统,用于软件的安装,更新和移除。阅读目录安装软件 列出与该包先关联的文件 显示包的版本 移除软件(保留配置) 移除软件(不保留配置) 查找包的详细信息 列出deb包的内容安装软件命令:dpkg-i<.debfilename>实例:dpkg-i~/Download/mozybackup_i386.debmozybackup_i386.deb是手动下…

  • 马赛克还原神器—Depix,真的有那么神吗?「建议收藏」

    马赛克还原神器—Depix,真的有那么神吗?「建议收藏」Depix是用于从马赛克中还原密码/英文数字组合的Python工具。它的官方效果是这样的:效果非常令人惊艳,恢复后基本和原文图相差无几。但是真的有那么神吗?老规矩,需要打包好的软件关注小编,QQ群:721195303领取。01怎么做到的?第一步,作者在编辑器中使用了与原图(带有马赛克的图片)相同的字体设置(文本大小,字体,颜色等设置),然后将debruinseq.txt内的文字和数字放入编辑器中并截图,这张截图中的所有文字都将被像素化后作为“搜索集”来识别原图中马赛克的真实..

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号