awk、grep、sed命令学习

2022-09-05 14:32:13 浏览数 (1)

Contents

  • 1 awk
    • 1.1 awk 内建变量
    • 1.2 awk 的逻辑运算字符
    • 1.3 awk 总结
  • 2 sed
  • 3 shell 脚本实例
  • 4 参考资料

从很多学习资料都了解到,awk、grep、sed是必须掌握的linux命令之一。

awk、grep、sedlinux 操作文本的三大利器,也是必须掌握的 linux 命令之一。三者的功能都是处理文本,但侧重点各不相同,其中属 awk 功能最强大,但也最复杂。grep 更适合单纯的查找或匹配文本,sed 更适合编辑匹配到的文本,awk 更适合格式化文本,对文本进行较复杂格式处理

awk

awk 是一个非常好的数据处理工具,相比于 sed 常常作用于一整行的处理, awk 则比较倾向于一行当中分成数个 字段 来处理。因此,其适合于小型的数据处理,其命令使用模式如下:

代码语言:javascript复制
awk '条件类型'{动作1} 条件类型2{动作2} ...'     

awk 后面接两个单引号并加上大括号 {} 来设定想要对数据进行的处理动作。 awk 可以处理后续接的文件,也可以读取来自前个指令的 standard outputawk 主要是处理『每一行的字段内的数据』,而默认的『字段的分隔符为 “空格键” 或 “[tab]键” 』 !(这句话可能比较难理解),直接看下面例子: 使用 last 命令可以将 Linux系统最近的登入者数据打印出来(只取前 5 行),命令如下:

代码语言:javascript复制
last -n 5

结果如下:

zhixuan. pts/154 192.64.38.114 Thu Aug 15 15:20 still logged in pengxian pts/153 192.164.37.159 Thu Aug 15 15:19 still logged in pengxian pts/152 192.164.37.159 Thu Aug 15 15:13 still logged in xinkuan. pts/150 192.191.38.17 Thu Aug 15 15:10 still logged in xinkuan. pts/128 192.131.38.17 Thu Aug 15 15:09 still logged in

但是我们想要取出登入者的 IP,且账号与 IP 之间以 [tab] 隔开,命令如下:

代码语言:javascript复制
last -n 5| awk '{print $1 "t" $3}'

结果如下:

zhixuan. 192.64.38.114 zhixuan. 153 192.164.37.159 pengxian 152 192.164.37.159 pengxian 192.191.38.17 xinkuan. 192.131.38.17

awk 是『以行为一次处理的单位』, 而『以字段为最小的处理单位』。在这里 last 打印的每一行数据都是我要处理的,因此,就不需要“条件类型”的限制,在 awk 括号内,每一行的每个字段都是有变量名称的,第一个字段是 1,第二个字段是 2,依次类推。总结可得,整个 awk 的处理流程如下:

  1. 读入第一行,并将第一行的资料填入 0, 1,
  2. 依据 “条件类型” 的限制,判断是否需要进行后面的 “动作”;
  3. 做完所有的动作与条件类型;
  4. 若还有后续的『行』的数据,则重复上面 1~3 的步骤,直到所有的数据都读完为止。

awk 内建变量

如果想要实现以下功能:

  • 列出每一行的账号(就是 $1 );
  • 列出目前处理的行数(就是 awk 内的 NR 变量)
  • 并且说明,该行有多少字段(就是 awk 内的 NF 变量)

使用命令:

代码语言:javascript复制
last -n 5|awk '{print $1 "t lines: " NR "t columns: " NF}' 

运行结果如下:

zhixuan. lines: 1 columns: 10 zhixuan. lines: 2 columns: 10 pengxian lines: 3 columns: 10 pengxian lines: 4 columns: 10 xinkuan. lines: 5 columns: 10

awk 的逻辑运算字符

awk 命令有用到条件类型,自然会涉及到逻辑运算符,如下表:

awk命令 的逻辑运算符

举例来说,在 /etc/passwd 当中是以冒号 ":" 来作为字段的分隔, 该文件中第一字段为账号,第三字段则是 UID。那假设要查阅,第三栏小于 10 以下的数据,并且仅列出账号与第三栏,可以使用以下命令:

代码语言:javascript复制
cat /etc/passwd | awk '{FS=":"} $3<10 {print $1 "t" $3}'

运行结果如下:

root:x:0:0:root:/root:/bin/bash bin 1 daemon 2 adm 3 …(以下省略)…

{}花括号里面是你想要做的动作的命令,比如这里要打印账号与第三栏所以有{print$1"t"$3}。这里,第一行没有正确的显示出来,这是因为我们读入第一行的时候,那些变数$1,$2...默认还是以空格键为分隔的,所以虽然我们定义了FS=":"了, 但是却仅能在第二行后才开始生效。那么怎么办呢?我们可以预先设定 awk 的变量啊!利用BEGIN这个关键词!使用如下命令:

代码语言:javascript复制
cat /etc/passwd | awk 'BEGIN {FS=":"} $3<10 {print $1 "t" $3}'

运行结果如下:

root 0 bin 1 daemon 2 …(以下省略)…

awk 总结

1,awk 的指令间隔:所有 awk 的动作,亦即在 {} 内的动作,如果有需要多个指令辅助时,可利用分号『;』间隔, 或者直接以[Enter]按键来隔开每个指令。 2,逻辑运算当中,如果是『等于』的情况,则务必使用两个等号『==』! 3,格式化输出时,在 printf 的格式设定当中,务必加上 n ,才能进行分行! 4,与 bash shell 的变量不同,在 awk 当中,变量可以直接使用,不需加上 $ 符号。

sed

sed 是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用 sed 命令处理缓冲区内容,处理完成后,把缓冲区内容送往屏幕。然后读入下行,执行下一个循环。如果没有使诸如 ‘D’ 的特殊命令,那会在两个循环之间清空模式空间,但不会清空保留空间。这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出或-i。

shell 脚本实例

使用如下命令查找指定目录下所有的 png 图片文件个数:

代码语言:javascript复制
ls -lR|grep -i '.*png' | wc -l

参考资料

《鸟哥的Linux私房菜-基础篇》

0 人点赞