awk详解
1. 概述
今天我们会将
awk
单独分为一个章节,因为其实awk
本身是可以作为一个体系的,所以单独拿出来一章 ,不过分
1.1 原理解析
- awk 认为文件中的每一行是一条记录,记录与记录的分隔符为换行符,每一列是一个字段 字段与字段的分隔符默认是一个或多个空格或tab制表符
- awk的工作方式是逐行读取文本数据,将每一行数据视为一条记录(record)每条记录以字段分隔符分成若干字段,然后输出各个字段的值.然后以查找匹配某个特定模式的文本行,并对这些文本执行制定动作
2. 格式
2.1 基本格式
格式:
awk [参数] '[动作]' [文件名]
awk [参数] –f 动作文件 var=value [文件名]
awk [参数] 'BEGIN段 [动作] END段' [文件名]
注意:
动作的格式 '匹配条件{打印动作}'
2.2 常见参数
常见参数:
-F 指定列的分隔符,默认一行数据的列分隔符是空格
-f file 指定读取程序的文件名
-v var=value 自定义变量
2.3 优先级
awk程序运行优先级是:
1 BEGIN: 在开始处理数据流之前执行,可选项
2 动作: 如何处理数据流,必选项
3 END: 处理完数据流后执行,可选项
2.4 常见动作
常见动作
print 显示内容
$0 显示当前行所有内容
$n 显示当前行的第n列内容,如果存在多个$n,它们之间使用逗号(,)隔开
注意:
如果打印的内容是变量,则无需在变量两侧加上双引号,其他的都应该加双引号
2.5 内置变量
常见内置变量
FILENAME 当前输入文件的文件名,该变量是只读的
NR 指定显示行的行号
FNR 多文件时候,分别计数
NF 表示字段数量
OFS 输出格式的列分隔符,缺省是空格
FS 输入文件的列分隔符,缺省是连续的空格和Tab
RS 输入记录分隔符,指定输入时的换行符,原换行符($)仍有效
ORS 输出记录分隔符,输出时用指定符号代替换行符
ARGC|ARGV[n] 获取命令的参数个数|参数内容
3. 综合示例
3.1 列打印
字段提取:提取一个文本中的一列数据并打印输出,它提供了相关的内置变量。
$0 表示整行文本
$1 表示文本行中的第一个数据字段
$2 表示文本行中的第二个数据字段
$N 表示文本行中的第N个数据字段
$NF 表示文本行中的最后一个数据字段
NR 代表行的行号,在动作外部表示特定行
注意:
如果打印多列信息,需要使用逗号隔开,否则是内容合并
3.1.1 单列打印
[root@VM-8-3-centos day03]# cat awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
[root@VM-8-3-centos day03]# awk '{print $1}' awk.txt
nihao
nihao
nihao
[root@VM-8-3-centos day03]#
3.1.2 多列打印
[root@VM-8-3-centos day03]# cat awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
[root@VM-8-3-centos day03]# awk '{print $1,$NF}' awk.txt
nihao awk3
nihao awk6
nihao awk9
[root@VM-8-3-centos day03]#
3.1.3 合并打印
[root@VM-8-3-centos day03]# cat awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
[root@VM-8-3-centos day03]# awk '{print $1$NF}' awk.txt
nihaoawk3
nihaoawk6
nihaoawk9
[root@VM-8-3-centos day03]#
3.1.4 行号打印
[root@VM-8-3-centos day03]# cat awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
[root@VM-8-3-centos day03]# awk '{print NR,$1}' awk.txt
1 nihao
2 nihao
3 nihao
[root@VM-8-3-centos day03]#
3.1.5 打印所有
[root@VM-8-3-centos day03]# cat awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
[root@VM-8-3-centos day03]# awk '{print $0}' awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
[root@VM-8-3-centos day03]#
3.2 定制查看
常见参数:
-F 指定列的分隔符,默认一行数据的列分隔符是空格
常见内置变量
FS 输入文件的列分隔符,缺省是连续的空格和Tab
RS 输入记录分隔符,指定输入时的换行符,原换行符($)仍有效
注意:
一般情况下,在输出信息之前进行格式的调整,需要在BEGIN{}部分设定
3.2.1 准备信息
[root@VM-8-3-centos day03]# head -n 1 /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@VM-8-3-centos day03]# head -n 1 /etc/passwd > passwd.txt
[root@VM-8-3-centos day03]# ll
total 8
-rw-r--r-- 1 root root 63 Feb 28 09:44 awk.txt
-rw-r--r-- 1 root root 32 Feb 28 10:13 passwd.txt
[root@VM-8-3-centos day03]# cat passwd.txt
root:x:0:0:root:/root:/bin/bash
[root@VM-8-3-centos day03]#
3.2.2 -F
定制分隔符
[root@VM-8-3-centos day03]# cat passwd.txt
root:x:0:0:root:/root:/bin/bash
[root@VM-8-3-centos day03]# awk -F ':' '{print $1,$NF}' passwd.txt
root /bin/bash
[root@VM-8-3-centos day03]#
3.2.3 -v FS
定制分隔符
[root@VM-8-3-centos day03]# cat passwd.txt
root:x:0:0:root:/root:/bin/bash
[root@VM-8-3-centos day03]# awk -v FS=':' '{print $1,$NF}' passwd.txt
root /bin/bash
[root@VM-8-3-centos day03]#
3.2.4 统计案例
[root@VM-8-3-centos day03]# vi domain.txt
[root@VM-8-3-centos day03]# cat domain.txt
http://www.example.org/index.html
http://www.example.org/1.html
http://api.example.org/index.html
http://upload.example.org/index.html
http://img.example.org/3.html
http://search.example.org/2.html
[root@VM-8-3-centos day03]# awk -F[/]+ '{print $2}' domain.txt | uniq -c
2 www.example.org
1 api.example.org
1 upload.example.org
1 img.example.org
1 search.example.org
[root@VM-8-3-centos day03]#
3.3 显示语法
3.3.1 基本格式
属性方法
OFS 输出格式的列分隔符,缺省是空格
ORS 输出记录分隔符,输出时用指定符号代替换行符
print方法
printf [-v var] format [item1,item2,...]
注意:
printf输出需要指定换行符号,format的格式必须与后面item对应
常见格式:
%c 显示字符的ASCII码 %d|i 显示十进制整数
%e|E 显示科学计数法数值 %u 显示无符号整数
%f 显示浮点数 %s 显示字符串
%% 显示%本身
修饰符:
%#[.#] 第一个#控制显示宽度,第二个#表示小数点后的精度,例如%3.1f
%- 左对齐,%-15s
%+ 显示数值的正负符号,%+d
3.3.2 定制列分隔符
[root@VM-8-3-centos day03]# awk -F ':' -v OFS='~~' '{print $1,$NF}' passwd.txt
root~~/bin/bash
[root@VM-8-3-centos day03]#
3.3.3 printf 格式化输出实践
使用print的格式信息
[root@localhost ~]# awk '{printf "%s\n",$1}' awk.txt
nihao
nihao
nihao
[root@localhost ~]# awk '{printf "%s",$1}' awk.txt; echo
nihaonihaonihao
多信息格式化嵌套
[root@localhost ~]# awk '{printf "%d--%s--%s\n", NR,$1,$NR}' awk.txt
1--nihao--nihao
2--nihao--awk4
3--nihao--awk8
数字的格式化输出
[root@localhost ~]# awk '{printf "%4.2f--%s\n", NR,$1}' awk.txt
1.00--nihao
2.00--nihao
3.00--nihao
字符的格式化输出
[root@localhost ~]# awk '{printf "%-8s%s\n", NR,$1}' awk.txt
1 nihao
2 nihao
3 nihao
3.4 优先级实践
格式显示:
BEGIN{}: 读入第一行文本之前执行的语句,一般用来初始化操作
{}: 逐行处理的执行命令
END{}: 处理完最后以行文本后执行,一般用来处理输出结果
3.4.1 优先级实践1
[root@VM-8-3-centos day03]# awk -F: 'BEGIN{print "begin中的NR值:" NR} {print "命令中的NR值: " NR}END{print "END中的NR值: " NR}' /etc/passwd
3.4.2 打印header 以及内容
打印效果如下
[root@VM-8-3-centos day04]# awk 'BEGIN{print "第一列\t第二列\t"} {print $1"\t"$NF}' awk.txt
第一列 第二列
nihao awk3
nihao awk6
nihao awk9
3.4.3 组合格式化打印
[root@VM-8-3-centos day04]# awk 'BEGIN{print "第一列\t第二列\n--------------------"} {print $1"\t"$NF;total=NR} END{print "------------------\n总数是:" total}' awk.txt
第一列 第二列
--------------------
nihao awk3
nihao awk6
nihao awk9
------------------
总数是:3