[转帖]awk 文本处理

awk,文本处理 · 浏览次数 : 0

小编点评

**awk 的记录处理示例** 以下是一些使用 awk 处理记录的示例: **使用分隔符** ```awk -F "," '{print $1,$2,$3}' people.txt # 输出第一列,第二列,第三列的值 line1:root x 0line2:daemon x 1line3:bin x 2line4:sys x 3 **使用输出记录分隔符** ```awk -F "\\" -v RS="\\"\ '{print $1,$2,$3}' people.txt # 输出第一列,第二列,第三列的值 record1:P1 record2:male record3:15 record4: record5:p2 record6:female record7:20 record8: record9:p3 record10:male record11:19 record12:root x 0record13:daemon x 1record14:bin x 2record15:sys x 3 ``` **使用输出记录分隔符和输出记录数量** ```awk -F ":" '{print "record" NR "\":\" $1,$2,$3}' /etc/passwd # 输出记录,每行包含记录数量 record1:P1 record2:male record3:15 record4: record5:p2 record6:female record7:20 record8: record9:p3 record10:male record11:19 record12:root x 0record13:daemon x 1record14:bin x 2record15:sys x 3 ``` **使用条件语句** ```awk -F ":" 'if ($3==0)print $0' /etc/passwdroot:x:0:0:root:/root:/usr/bin/zsh # 输出第三个字段等于 0 的记录 ``` **使用循环语句** ```awk -v ORS=\",\" 'BEGIN{ for(i=1;i<5;i++) print i}' 1,2,3,4, # 输出 1 到 4 之间的数字 ```

正文

https://juejin.cn/post/6844903860629143559

 

awk 文本处理

awk 文本处理

awk 是一种样式扫描和处理语言,使用 Linux 的 awk 命令可以高效快捷地进行文本处理。awk 扫描文本的每一行并执行指定的命令。

awk 诞生于 1977 年,借鉴了 C 语言等编程语言,名字取自三位设计者 Alfred Aho、Peter Weinberger 和 Brian Kernighan 的姓氏。awk 的版本众多,本文中使用的是 Ubuntu 上的 GNU Awk,在 MacOS 上可以使用 HomeBrew 安装 gawk。

用法

awk 可以直接在命令行中执行,也可以编写.awk后缀的文件然后执行。awk 以行为单位进行文本处理,对于接收到的每一行都会执行指定的行为。

命令行执行

$ awk [ -F fs ] [ -v var=value ] 'pattern {action}' [ file ...  ]
复制代码

其中 -F 指定分隔符,-v 指定 awk 的内置变量。

例如对于 /etc/passwd 文件中的内容:

root:x:0:0:root:/root:/usr/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
复制代码

如果要输出每一行的内容,可以使用

$ awk '{print $0}' /etc/passwd
复制代码

其中 $0 表示扫描到的文本行。

文件执行

.awk 文件可以分成三个部分来写,如下:

# passwd.awk

BEGIN{
  FS="\n";
  print "Before action";
}
{
  print $0;
}
END{
  print "After action";
}
复制代码

BEGIN 块用于定义处理每一行之前的行为,可以用来设置 awk 的内置变量,设置好后在后面处理每一行时都会生效。

END 块用于定义处理完文本之后的行为,可以用来输出一些总结信息。

BEGIN 和 END 中间的块是对于每一行的操作。直接在命令行中执行 awk 时也可以用 BEGIN 和 END 块。

写好文件后在命令行中执行:

Before action
root:x:0:0:root:/root:/usr/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
After action
复制代码

变量

$ + 数字

$0 表示扫描到的行,$1表示将该行分隔后的第 1 项,$2表示将该行分隔后的第 2 项,以此类推。

为了输出 /etc/passwd 的用户名(第一项),可以执行下面语句:

$ awk -F ':' '{print $1}' /etc/passwd
root
daemon
bin
sys
复制代码

这里以处理第一行 root:x:0:0:root:/root:/usr/bin/zsh 为例,awk 处理是会先按照 -F 设置的分隔符 : 将这行分割为 root​ x ​0 0 root /root /usr/bin/zsh然后输出第一项 root

特殊变量

  1. FS(field separator)

    FS 是输入字段分隔符,例如上面设置的 :,其默认值是空格,可以在命令行中使用 -F 设置,也可以在 BEGIN 块中通过 FS= 设置为某个字符串或者一个正则表达式。例如:

    $ awk -F ":" '{print $1,$2,$3}' /etc/passwd
    root x 0
    daemon x 1
    bin x 2
    sys x 3
    复制代码
  2. OFS(output field separator)

    OFS 是输出字段连接符,上面例子中的输出默认使用空格作为输出字段连接符,通过设置 OFS 变量进行修改:

    $ awk -F ":" -v OFS="-" '{print $1,$2,$3}' /etc/passwd
    root-x-0
    daemon-x-1
    bin-x-2
    sys-x-3
    复制代码
  3. RS(record separator)

    前面提到的例子中,awk 都默认以行为单位处理文本,每一行保存了一条记录,这是因为默认的记录分隔符 RS 为 "\n"。还有一些文本在存储时并不是想 csv 等文件一样以行单位,例如:

    # people.txt
    
    P1
    male
    15
    
    p2
    female
    20
    
    p3
    male
    19
    复制代码

    上面的文件中使用 "\n\n" 分隔记录,每个记录中又使用 "\n" 分隔字段,可以这样处理:

    $ awk -F "\n" -v RS="\n\n" '{print $1,$2,$3}' people.txt 
    P1 male 15
    p2 female 20
    p3 male 19
    复制代码
  4. ORS(output field separator)

    与 RS 类似,ORS 设置输出的记录分隔符。

    $ awk -F "\n" -v RS="\n\n" -v ORS="\n***\n" '{print $1,$2,$3}' people.txt
    P1 male 15
    ***
    p2 female 20
    ***
    p3 male 19
    ***
    复制代码
  5. NR(number of records)

    NR 表示当前正在处理的记录的是第几项,如果 NR 出现在 END 块中则表示已处理的记录数

    $ awk -F ":" '{print "line" NR ":" $1,$2,$3}' /etc/passwd           
    line1:root x 0
    line2:daemon x 1
    line3:bin x 2
    line4:sys x 3
    复制代码

    如果同时处理多个文件,那么这个项数会累加

    $ awk -F ":" '{print "record" NR ":" $1,$2,$3}' people.txt /etc/passwd
    record1:P1  
    record2:male  
    record3:15  
    record4:  
    record5:p2  
    record6:female  
    record7:20  
    record8:  
    record9:p3  
    record10:male  
    record11:19  
    record12:root x 0
    record13:daemon x 1
    record14:bin x 2
    record15:sys x 3
    复制代码
  6. NF(number of fields)

    NF 表示一条记录中分隔后的字段数,因此这个值与设置的 FS 有关:

    # 以 ":" 为分隔符
    $ awk -F ":" '{print "record" NR " with " NF " fields:" $1,$2,$3}' /etc/passwd
    record1 with 7 fields:root x 0
    record2 with 7 fields:daemon x 1
    record3 with 7 fields:bin x 2
    record4 with 7 fields:sys x 3
    
    # 以 "o" 为分隔符
    $ awk -F "o" '{print "record" NR " with " NF " fields:" $1,$2,$3}' /etc/passwd
    record1 with 7 fields:r  t:x:0:0:r
    record2 with 5 fields:daem n:x:1:1:daem n:/usr/sbin:/usr/sbin/n
    record3 with 3 fields:bin:x:2:2:bin:/bin:/usr/sbin/n l gin
    record4 with 3 fields:sys:x:3:3:sys:/dev:/usr/sbin/n l gin
    复制代码
  7. FILENAME

    FILENAME 是当前正在处理的文件的名字

    $ awk -F ":" '{print FILENAME}' /etc/passwd people.txt
    /etc/passwd
    /etc/passwd
    /etc/passwd
    /etc/passwd
    people.txt
    people.txt
    people.txt
    people.txt
    people.txt
    people.txt
    people.txt
    people.txt
    people.txt
    people.txt
    people.txt
    复制代码

    这个值在开始处理记录后才有意义,因此在 BEGIN 块中尝试输出 FILENAME 将得到空值

  8. FNR

    前面的 NR 表示的项数在处理多个文件时会累加,而FNR 表示记录位于当前文件的第几项

    awk -F ":" '{print "record" FNR ":" $1,$2,$3}' people.txt /etc/passwd
    record1:P1  
    record2:male  
    record3:15  
    record4:  
    record5:p2  
    record6:female  
    record7:20  
    record8:  
    record9:p3  
    record10:male  
    record11:19  
    record1:root x 0
    record2:daemon x 1
    record3:bin x 2
    record4:sys x 3 
    复制代码

内置函数

awk 提供了一些内置函数,便于文本和运算的处理,包括获取字符串长度的 length(),获取随机数的 rand(),计算正余弦的 sin() 和 cos()

这些函数可以在官方手册中查询。

记录筛选

上面的所有的例子都对每一条记录进行了操作,事实上还可以用条件进行筛选。

正则判断

使用正则表达式可以对记录进行模式匹配:

$ awk -F ':' '/root/ {print $1,$2,$3}' /etc/passwd 
root x 0
复制代码

这里筛选出了包含 root 的记录。

条件判断

结合 awk 的内置变量和函数也可以进行筛选:

# 输出第一个字段长度大于 2 且在 第 1 条记录之后的记录
$ awk -F ':' 'length($1)>3 && NR>1 {print $0}' /etc/passwd
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
复制代码

if 语句

awk 也提供了 if 语句:

# 输出第 3 个字段为 0 的记录
$ awk -F ':' '{if ($3==0)print $0}' /etc/passwd
root:x:0:0:root:/root:/usr/bin/zsh
复制代码

awk 还有 for 语句,与 C 语言中形式类似:

$ awk -v ORS="," 'BEGIN{ for(i=1;i<5;i++) print i}'  
1,2,3,4,
复制代码

字符与数字

awk 提供了对数学运算符和逻辑运算符的支持的支持,在 awk 中字符串与数字间还可以直接进行强制类型转换,+0 可以强制转换为数字,与空格拼接可以转换为字符串:

awk 'BEGIN{print "origin\tnumber\tstring"}{print $0,"\t",$0+0,"\t",$0 ""}' people.txt
origin  number  string
P1       0       P1
male     0       male
15       15      15
         0       
p2       0       p2
female   0       female
20       20      20
         0       
p3       0       p3
male     0       male
19       19      1
复制代码

这里使用了 $0 "" 的表示方式将原记录与空格进行了拼接,但在某些情况下会出现问题,考虑下面的语句:

$ awk 'BEGIN { print -12 " " -24 }'
-| -12-24
复制代码

这里想要在 -12 和 -24 中间加一个空格,但没有得到想要的结果,这是由于数学运算符的优先级高于拼接操作,所以解析顺序如下:

   -12 (" " - 24)
⇒ -12 (0 - 24)
⇒ -12 (-24)
⇒ -12-24
复制代码

要得到正确的正确的结果需要使用括号结合:

$ awk 'BEGIN { print -12 " " (-24) }'
-| -12 -24

与[转帖]awk 文本处理相似的内容:

[转帖]awk 文本处理

https://juejin.cn/post/6844903860629143559 awk 文本处理 awk 是一种样式扫描和处理语言,使用 Linux 的 awk 命令可以高效快捷地进行文本处理。awk 扫描文本的每一行并执行指定的命令。 awk 诞生于 1977 年,借鉴了 C 语言等编程语言

[转帖]Linux-文本处理三剑客awk详解+企业真实案例(变量、正则、条件判断、循环、数组、分析日志)

https://developer.aliyun.com/article/885607?spm=a2c6h.24874632.expert-profile.313.7c46cfe9h5DxWK 简介: 文本处理 awk 1.awk简介 awk是一种编程语言,用于在Linux/unix下对文本和数据进

[转帖]Linux文本处理三剑客之awk学习笔记05:getline用法详解

https://www.cnblogs.com/alongdidi/archive/2021/01/19/awkGetline.html getline用法详解 在默认情况下,awk支持从文件或者STDIN中读取数据。我们也可以使用getline来灵活读取数据,例如在main代码块执行过程中读取某个

[转帖]Linux文本处理三剑客之awk学习笔记05:getline用法详解

https://www.cnblogs.com/alongdidi/p/awkGetline.html getline用法详解 在默认情况下,awk支持从文件或者STDIN中读取数据。我们也可以使用getline来灵活读取数据,例如在main代码块执行过程中读取某个非待处理文件的数据,或者从某个读取

[转帖]Linux下AWK、SED、GREP、FIND命令详解

https://www.jianshu.com/p/d54e0359db01 AWK AWK是一个优良的文本处理工具,Linux和Unix环境中现有的功能最强大的数据处理引擎之一。 语法 awk [选项参数] 'script' var=value file(s) 或 awk [选项参数] -f sc

[转帖] Linux命令拾遗-文本处理篇

https://www.cnblogs.com/codelogs/p/16060413.html 简介# 这是Linux命令拾遗系列的第二篇,本篇主要介绍Linux中与文本处理相关的命令,如xargs、grep、sed、awk等。 本系列文章索引Linux命令拾遗-入门篇 常用文本相关命令# cat

[转帖] Linux文本命令技巧(上)

Linux文本命令技巧(上) 原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介# 前一篇我介绍了awk,这是一个全能的文本处理神器,因为它本身就是一门编程语言了,但对于很多场景,使用Linux预设的一些文本处理命令,会更方便快捷,如grep、sed等。本篇就来介绍

[转帖]19.awk报告生成器,文本解释器

在本博客中,AWK是一个系列文章,本人会尽量以通俗易懂的方式递进的总结awk命令的相关知识点。 awk系列博文直达链接:AWK命令总结之从放弃到入门 我们先来用专业的术语描述一下awk是什么,如果你看不懂,没关系,我们会再用”大白话”解释一遍。 awk是一个报告生成器,它拥有强大的文本格式化的能力,

[转帖]SHELL—— awk两个特殊模式(BEGIN 和 END)及awk高级应用(条件判断、循环)

一、Awk 的两个特殊模式 BEGIN 和 END,BEGIN 被放置在没有读取任何数据之前,而 END 被放置在所有的数据读取完成以后执行体现如下: BEGIN{}: 读入第一行文本之前执行的语句,一般用来初始化操作 {}: 逐行处理 END{}: 处理完最后以行文本后执行,一般用来处理输出结果

[转帖]Linux系统awk命令详解

AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。 之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。 实际上 AWK 的确拥有自己的语言: AWK程序设计语言,三位