Contents
- 1 awk
- 1.1 awk 内建变量
- 1.2 awk 的逻辑运算字符
- 1.3 awk 总结
- 2 sed
- 3 shell 脚本实例
- 4 参考资料
从很多学习资料都了解到,
awk、grep、sed
是必须掌握的linux命令之一。
awk、grep、sed
是 linux
操作文本的三大利器,也是必须掌握的 linux
命令之一。三者的功能都是处理文本,但侧重点各不相同,其中属 awk
功能最强大,但也最复杂。grep
更适合单纯的查找或匹配文本,sed
更适合编辑匹配到的文本,awk
更适合格式化文本,对文本进行较复杂格式处理。
awk
awk
是一个非常好的数据处理工具,相比于 sed
常常作用于一整行的处理, awk
则比较倾向于一行当中分成数个 字段 来处理。因此,其适合于小型的数据处理,其命令使用模式如下:
awk '条件类型'{动作1} 条件类型2{动作2} ...'
awk
后面接两个单引号并加上大括号 {}
来设定想要对数据进行的处理动作。 awk
可以处理后续接的文件,也可以读取来自前个指令的 standard output
。 awk
主要是处理『每一行的字段内的数据』,而默认的『字段的分隔符为 “空格键” 或 “[tab]键” 』 !(这句话可能比较难理解),直接看下面例子:
使用 last
命令可以将 Linux
系统最近的登入者数据打印出来(只取前 5 行),命令如下:
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]
隔开,命令如下:
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 的处理流程如下:
- 读入第一行,并将第一行的资料填入 0, 1,
- 依据 “条件类型” 的限制,判断是否需要进行后面的 “动作”;
- 做完所有的动作与条件类型;
- 若还有后续的『行』的数据,则重复上面
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
以下的数据,并且仅列出账号与第三栏,可以使用以下命令:
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
这个关键词!使用如下命令:
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
图片文件个数:
ls -lR|grep -i '.*png' | wc -l
参考资料
《鸟哥的Linux私房菜-基础篇》