linux-awk常用命令
语法
awk [options] ‘Pattern{Action}’ file
常用参数
参数 | 作用 |
---|---|
-F | 指定输入文件的分隔符 |
-v | 赋值一个用户变量 |
-f | 从脚本文件中读取awk命令 |
准备2个文件:test1.txt,test2.txt
打印全文
awk '{print}' test1.txt
awk '{print $0}' test1.txt
指定分隔符:
,并打印第一列。默认分割符是空格
awk '{print $1}' test1.txt
awk -F ':' '{print $1}' test1.txt
同时指定冒号 :
和空格' '
作为分割符,打印1,3列
awk -F ' |:' '{print $1,$3}' test1.txt
变量
内置变量
awk 常用内置变量
变量 | 作用 |
---|---|
FS | 输入字段分隔符,默认为空白字符 |
OFS | 输出字段分隔符,默认为空白字符 |
RS | 输入行分割符,默认是回车换行 |
ORS | 输出记录分割符(输入换行符),输出时用指定符号代替换行符 |
NF | 当前行的字段的个数(即当前行被分割成了几列),字段数量 |
NR | 行号,当前处理的文本行的行号。 |
FNR | 各文件分别计数的行号 |
FILENAME | 当前文件名 |
ARGC | 命令行参数的个数 |
ARGV | 数组,保存的是命令行所给定的各参数 |
NR,NF,FNR
NR 表示每一行的行号,NF 表示一行中共有几列。默认分隔符是空格
awk '{print NR,NF}' test1.txt
awk -F ' |:' '{print NR,NF}' test1.txt
打印最后一列,不知道行号可以用 $NF 表示
awk '{print $NF}' test1.txt
多个文件分别统计行号用 FNR
awk '{print NR,$0}' test1.txt test2.txt
awk '{print FNR,$0}' test1.txt test2.txt
FILENAME 显示文件名
awk '{print FNR,$0}' test1.txt test2.txt
awk '{print FILENAME,FNR,$0}' test1.txt test2.txt
ARGC 和 ARGV
ARGV 表示数组,在 awk 中 ARGV[0] 表示 awk,ARGC 表示参数个数
建 3.txt 和 4.txt 两个文件
打印数组的话会根据后面文件里面的行数显示,如果文件里面什么都没有就没有输出
awk -F ':' '{print $1,ARGV[0],ARGV[1],ARGV[2],ARGC}' test1.txt test2.txt
awk -F ':' '{print $1,ARGV[0],ARGV[1],ARGV[2],ARGC}' test2.txt 3.txt
awk -F ':' '{print $1,ARGV[0],ARGV[1],ARGV[2],ARGC}' 3.txt 4.txt
自定义变量
用 -v 指定变量名或者在 program 中直接定义。
awk -v value="test1" 'BEGIN{print value}'
awk 'BEGIN{value="test1";print value}'
格式化
格式替换符 | 作用 |
---|---|
%s | 字符串 |
%f | 浮点格式(也就是我们概念中的 float 或者 double) |
%b | 相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义。 |
%c | ASCII 字符。显示相对应参数的第一个字符 |
%d, %i | 十进制整数 |
%% | 表示 ”%” 本身 |
转义符 | 作用 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
在 awk 中使用 printf 动作时的注意事项
1、使用 printf 动作输出的文本不会换行,如果需要换行,可以在对应的”格式替换符”后加入”\n” 进行转义。
2、使用 printf 动作时,”指定的格式” 与 “被格式化的文本” 之间,需要用 ”逗号” 隔开。
3、使用 printf 动作时,”格式” 中的 ”格式替换符” 必须与 “被格式化的文本” 一一对应。
awk '{printf "第一列:%s 第二列:%s\n" , $1,$2}' test1.txt
打印表头
awk 'BEGIN{printf "%s\t %s\n", "第一列","第二列"}{printf "%s\t %s\n",$1,$2}' test1.txt
数字可以设置输出的宽度
awk 'BEGIN{printf "%5s\t %5s\n", "第一列","第二列"}{printf "%5s\t %5s\n",$1,$2}' test1.txt
默认每一列靠右对齐,加 -
靠左对齐
awk 'BEGIN{printf "%-5s\t %-5s\n", "第一列","第二列"}{printf "%-5s\t %-5s\n",$1,$2}' test1.txt
对于数字可以用 +
显示正数前面的加号,不是数字的话会被转换成 0
awk 'BEGIN{printf "%+5s\t %+5s\n", "第一列","第二列"}{printf "%-+5d\t %-+5d\n",$1,$2}' test1.txt
模式
当 awk 进行逐行处理的时候,会把 pattern(模式)作为条件,判断将要被处理的行是否满足条件,是否能跟 ”模式” 进行匹配,如果匹配,则处理,如果不匹配,则不进行处理。
空模式
没指定任何模式即为空模式,空模式会匹配文本中的每一行,所以,每一行都会执行相应的动作。
匹配所有行并打印第一个字段
awk '{print $1}' test1.txt
关系运算模式
关系运算符 | 含义 |
---|---|
< | 小于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
>= | 大于等于 |
> | 大于 |
~ | 与对应的正则匹配则为真 |
!~ | 与对应的正则不匹配则为真 |
如果第一列的数字为 2,打印该行
awk '$1==2 {print $0}' test1.txt
awk '$1==2' test1.txt
正则模式
打印以 A 开头的行
awk '/^A/ {print $0}' test1.txt
与关系运算模式结合使用用 ~
或者!~
连接
打印第二列为字母的行
awk '$2~/[a-z]/ {print $0}' test1.txt
打印第二列不为字母的行
awk '$2!~/[a-z]/ {print $0}' test1.txt
行范围模式
打印第二列为 2 到 3 之间的行
awk '/2/,/3/' test1.txt
awk '/2/,/3/ {print $0}' test1.txt
打印第二列为 2 到 a 之间的行
awk '/2/,/a/' test1.txt
awk '/2/,/a/ {print $0}' test1.txt
BEGIN/END 模式
BEGIN 模式指定了处理文本之前需要执行的操作,END 模式指定了处理完所有行之后所需要执行的操作。
先打印 start,然后打印 test1 文件中的第一列,最后打印 end
awk 'BEGIN{print "start"} {print $1} END{print "end"}' test1.txt
条件语句与循环
打印序列,并在第一列的下面打印第二列
awk '{print $1}{print $2}' test1.txt
awk '{print $1; print $2}' test1.txt
条件语句
IF语句
如果行号为 1 ,打印该行
awk '{if(NR == 1){print $0}}' test1.txt
IF-ELSE语句
如果行号小于等于 2 ,打印该行并在后面加上一列 "条件一",否则打印改行并在后面加上一列 "条件二"
awk '{if(NR<=2){print $0,"条件一"}else{print $0,"条件二"}}' test1.txt
awk '{if(NR<=2)print $0,"条件一";else print $0,"条件二"}' test1.txt
IF-ELSE-IF语句
如果行号等于 1,打印该行并在后面加上一列 "第一行",如果行号等于 2 ,打印该行并在后面加上一列 "第二行",如果行号等于 3 ,打印该行并在后面加上一列 "第三行"
awk '{if(NR==1){print $0, "第一行"} else if(NR==2){print $0,"第二行"} else if(NR==3){print $0,"第三行"}}' test1.txt
awk '{if(NR==1)print $0, "第一行"; else if(NR==2)print $0,"第二行"; else if(NR==3)print $0,"第三行"}' test1.txt
循环
For
awk '{for(i=1;i<=NF;++i) print $i,i}' test1.txt
While
awk '{i=1; while(i<=NF-1){print $0,++i}}' test1.txt
Break
awk '{for(i=1;i<=NF;++i){if(i==2)break;print $i,i}}' test1.txt
Continue
awk '{for(i=1;i<=NF;++i){if(i<=2)continue;print $i,i}}' test1.txt
Exit
exit 表示退出 awk 命令。当 awk 语句中有 exit
和 END{commands}语句块
的时候,exit 并不是表示退出 awk 命令,而是表示直接执行 END{commands} 语句块中的内容!
awk 'NR==1{print $0} NR==2{print $0}' test1.txt
awk 'NR==1{print $0;exit} NR==2{print $0}' test1.txt
awk 'NR==1{print $0;exit} NR==2{print $0} END{print "end"}' test1.txt
数组
数组使用的语法格式
array_name[index]=value
array_name:数组的名称
index:数组索引
value:数组中元素所赋予的值
创建数组
awk 'BEGIN{group["yi"]="一"; group["er"]="二";print group["yi"]"\n"group["er"]}'
删除数组元素
delete array_name[index]
awk 'BEGIN{group["yi"]="一"; group["er"]="二";delete group["yi"];print group["yi"]"\n"group["er"]}'
常用内置函数
函数名 | 作用 |
---|---|
int(X) | 返回 X 的截断至整数的值 |
rand() | 返回任意数字 n,其中 0 <= n < 1 |
srand(x) | 建立 rand() 的新的种子数,如果没有指定种子数目,就用当天的时间。返回旧的种子数 |
gsub(r,s,t) | 在字符串 t 中,用字符串 s 替换和正则表达式 r 匹配的所有字符串。返回替换的个数,如果没有给出 t,默认为 $0 |
length(s) | 返回字符串 s 的长度,当没有给出 s 时,返回 $0 的长度 |
split(s,a,sep) | 使用字段分隔符 sep 将字符串 s 分解到数组 a 的元素中,返回元素的个数。如果没有给出 sep,则使用 FS。数组分隔和字段分隔采用同样的方式 |
sub(r,s,t) | 在字符串 t 中用 s 替换正则表达式 r 的首次匹配。如果成功则返回 1,否则返回 0,如果没有给出 t,则默认为 $0 |