awk
awk格式:
pattern{action statements;..}
#pattern必须是为非0 非空字符串 即为"真"时 action才会动作 ; 空值或者为0时,action为"假"不执行动作
#字符串必须用 "" 引起来,否则会被识别成变量
#由分隔符分隔的字段(列column,域field)标记$1,$2...$n称为域标识,$0为所有域
#如果省略action,则默认执行 print $0 的操作
awk
-F “分隔符” 指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符
-v var=value 变量赋值
-f 调用文件
BEGIN 仅在开始处理文件中的文本之前执行一次
END 仅在文本处理完成之后执行一次
awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
#跳过 /etc/passwd里的奇数行
[root@centos8 ~]# awk 'NR==2' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
#显示文件的第二行, 需要注意的时 NR==2 这是pattern,其实省略了{print $0},完整写起来应该是 awk 'NR==2{print $0}'
正则表达式:
[root@centos8 ~]#awk -F: '$0 ~ /root/{print $1}' /etc/passwd
#/etc/passwd里包含 root的行
[root@centos8 ~]#awk -F: '$0 ~ "^root"{print $1}' /etc/passwd
#/etc/passwd里包含 root开头的行
[root@centos8 ~]#awk '$0 !~ /root/' /etc/passwd
#/etc/passwd里包含 非root的行
逻辑运算:
awk -F: '$3>=0 && $3<=1000 {print $1,$3}' /etc/passwd
awk -F: '$3==0 || $3>=1000 {print $1,$3}' /etc/passwd
awk -F: '!($3==0) {print $1,$3}' /etc/passwd
awk -F: '!($3>=500) {print $1,$3}' /etc/passwd
[root@centos8 ~]#seq 10 | awk 'NR>=3 && NR<=6'
#打印 第三行到第六行 &&与表示全部满足条件,||表示其中之一
关系表达:
[root@centos8 ~]#awk '!1' /etc/passwd
#相当于没写{print $0},且1为真,应该打印全文,但非1,即0 ,0为假,便不做打印
[root@centos8 ~]#awk '!0' /etc/passwd
#实际上是输出了结果的,但我懒,没复制
[root@centos8 ~]#awk '"fgwag"' /etc/passwd
#实际上是输出了结果的,但我懒,没复制,因为有值,所以为真,便打印
[root@centos8 ~]# awk 'fgwag' /etc/passwd
[root@centos8 ~]# awk "fgwag" /etc/passwd
#这两种情况都不打印
条件表达式(三目表达式):
awk -F: '{$3>=1000?AA="haha":AA="wawa";print$1,AA}' /etc/passwd
#当/etc/passwd里以:作为分隔符的第三列满足>1000是打印$1,跟haha,不满足打印$!跟wawa
###########################################################################
数组:
#可以实现 k/v (键值对)功能
格式:
array_name[index-expression]
awk '!line[$0]++' "文件名"
#实现去重功能
[root@centos8 ~]\# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print weekdays[i]}}'
Tuesday
Monday
#遍历数组
[root@centos8 ~]# awk 'BEGIN{haha[1]="qwe";haha[2]="asd";haha[3]="zxc";for (i in haha){print i ":" haha[i]}}'
1:qwe
2:asd
3:zxc
#遍历显示下标
###########################################################################
函数:
rand():返回0和1之间一个随机数
srand():配合rand() 函数,生成随机数的种子
int():返回整数
length([s]):返回指定字符串的长度
sub(r,s,[t]):对t字符串搜索r表示模式匹配的内容,并将第一个匹配内容替换为s
gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容
split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…
system 函数:可以awk中调用shell命令
空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用""引用起来
自定义函数格式:
function name ( parameter, parameter, ... ) {
statements
return expression
}
高级玩法:
[root@centos8 ~]# seq 10 |awk 'i=!i'
1
3
5
7
9
[root@centos8 ~]# seq 10 |awk '!(i=!i)'
2
4
6
8
10
[root@centos8 ~]# seq 10 |awk '{i=!i;print i}'
1
0
1
0
1
0
1
0
1
0
条件判断(if else):语法
if(condition){statement;…}[else statement]
if(condition1){statement1}else if(condition2){statement2}else if(condition3){statement3}......else{statementN}
###########################################################################
printf
格式:printf “FORMAT”, item1, item2, ...
%c:显示字符的ASCII码
%d, %i:显示十进制整数
%e, %E:显示科学计数法数值
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%自身
修饰符:
\#[.\#] 第一个数字控制显示的宽度;第二个#表示小数点后精度,如:%3.1f
- 左对齐(默认右对齐) 如:%-15s
+ 显示数值的正负符号 如:%+d
awk -F: '{printf "%s",$1}' /etc/passwd
awk -F: '{printf "%s\n",$1}' /etc/passwd
awk -F: '{printf "%20s\n",$1}' /etc/passwd
awk -F: '{printf "%-20s\n",$1}' /etc/passwd
awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
awk -F: '{printf "Username: %s\n",$1}' /etc/passwd
awk -F: '{printf “Username: %sUID:%d\n",$1,$3}' /etc/passwd
awk -F: '{printf "Username: %25sUID:%d\n",$1,$3}' /etc/passwd
awk -F: '{printf "Username: %-25sUID:%d\n",$1,$3}' /etc/passwd
#例子
###########################################################################
运算符:
x+y, x-y, x*y, x/y, x^y, x%y
-x:转换为负数
+x:将字符串转换为数值
赋值操作符:
=, +=, -=, *=, /=, %=, ^=,++, --
#例子
[root@centos8 ~]#awk 'BEGIN{i=0;print i++,i}'
0 1
[root@centos8 ~]#awk 'BEGIN{i=0;print ++i,i}'
1 1
重要!!!重要
awk -v n=0 '!n++{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
awk -v n=0 '!n++{print $0}' /etc/passwd
1
#因为 为 "true"才print "false"就不print 所以第一次 n=0 取反 n=1 n=1条件为"真" 所以打印第一行 (!n++相当于匹配的条件也就是pattern,因为第一行满足了,所以打印第一行),第二次n++ n=1 取反1=0 条件为"假" 所以第二个条件不满足,不打印第二行,第三次n++ n=2 取反2=0 条件为"假" 所以第三个条件不满足,不打印第三行
重要!!!重要
[root@centos8 ~]#awk -F: '$3>=1000' /etc/passwd
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
wang:x:1000:1000:wang:/home/wang:/bin/bash
mage:x:1001:1001::/home/mage:/bin/bash
#当 /etc/passwd 以 ":" 作为分隔符 当第三列数字大于1000 才print $0
##########################################################################
#注意 变量使用前 请加 "-v" 选项, 且注意变量赋值时,要给字符串加 "" !!!!!!!
awk 变量:
FS 列的分隔符 等同于 -F
OFS 输出列的分隔符
#[root@centos8 ~]# awk -v FS=':' -v OFS='zxc ' '{print $1,$3,$5}' /etc/issue
\Szxc zxc
Kernel \r on an \mzxc zxc
zxc zxc
#$1,$3,$5 之间一定要加 "," 不然 OFS 不生效
RS 记录(行)的分隔符 默认换行符
ORS 记录(行)与记录(行)之间的分隔符 默认换行符
#[root@centos8 ~]# cat haha
1,2,2,3,;4,5,6,;zxc,af1,gawg;
gwag,
gwaghhgeh,2
4gesg;hesh,ghse;
[root@centos8 ~]# awk -v RS=';' -v ORS='\nzxc' '{print $1}' haha
1,2,2,3,
zxc4,5,6,
zxczxc,af1,gawg
zxcgwag,
zxchesh,ghse
zxc
zxc
#把默认的行与行之间的 换行 分隔符 换成了 ";" 把,默认输出的 换行 分隔符 换成了 "换行zxc" ###\n表示换行
NF 列的字段的数量
#[root@centos8 ~]# awk -F':' '{print NF}' /etc/passwd |head -3
7
7
7
[root@centos8 ~]# awk -F':' '{print $NF}' /etc/passwd |head -3
/bin/bash
/sbin/nologin
/sbin/nologin
[root@centos8 ~]# awk -F':' '{print $(NF-1)}' /etc/passwd |head -3
/root
/bin
/sbin
#NF 表示 列的分隔符字段数, $NF表示最后一列 $(NF-1)表示倒数第二列
NR 记录的编号 默认一行一条记录 #间接说明一个文件有多少行
[root@centos8 ~]# cat haha
1,2,2,3,;4,5,6,;zxc,af1,gawg;
gwag,
gwaghhgeh,2
4gesg;hesh,ghse;
[root@centos8 ~]# awk -v RS=';' '{print NR $0}' haha
11,2,2,3,
24,5,6,
3zxc,af1,gawg
4
gwag,
gwaghhgeh,2
4gesg
5hesh,ghse
6
#用 ";" 作为行的分隔符,且显示时添加个行号
[root@centos8 ~]# awk 'NR==2' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
# 超实用的技巧,显示文件里的第几行
FNR 个文件分别计数,记录号
awk '{print NR $0}' /etc/issue ~/haha
1\S
2Kernel \r on an \m
3
41,2,2,3,;4,5,6,;zxc,af1,gawg;
5gwag,
6gwaghhgeh,2
74gesg;hesh,ghse;
[root@centos8 ~]# awk '{print FNR $0}' /etc/issue ~/haha
1\S
2Kernel \r on an \m
3
11,2,2,3,;4,5,6,;zxc,af1,gawg;
2gwag,
3gwaghhgeh,2
44gesg;hesh,ghse;
# 多个文件的话,分别记录编号
FILENAME 当前的文件名字
awk '{print FILENAME $0}' /etc/issue
/etc/issue\S
/etc/issueKernel \r on an \m
/etc/issue
#显示当前的文件名在每行的行首
ARGC 显示参数个数
ARGV[] 显示数组里的每个参数
[root@centos8 ~]# awk '{print ARGC }' /etc/issue
2
2
2
[root@centos8 ~]# awk '{print ARGV[0]}' /etc/issue
awk
awk
awk
[root@centos8 ~]# awk '{print ARGV[1]}' /etc/issue
/etc/issue
/etc/issue
/etc/issue
#显示总的参数个数,已经每个参数都是那个
-v 自定义变量
awk -v test='hello gawk' 'BEGIN{print test}'
awk 'BEGIN{test="hello,gawk";print test}'
[root@centos8 ~]# awk '{print 1+5}'
asdf
6
#做算术运算,注意!!!! 非字符串不需要加 ""
awk -F : '{print $1"\t"$3}' /etc/passwd
# $1 $3 的分隔符是"TAB" ","是 "空格" 逗号不需要加"" \t 需要加""
df |awk '/^\/dev\/nv/{print $1,$5}'
/dev/nvme0n1p2 7%
/dev/nvme0n1p3 1%
/dev/nvme0n1p1 17%
#查看 分区 跟利用率 /需要转义
[root@centos8 ~]# df | awk -F'[ ]+|%' '/^\/dev.*/{print $1"\t"$5}'
/dev/nvme0n1p2 7
/dev/nvme0n1p3 1
/dev/nvme0n1p1 17
#升级版 查看分区跟利用率
[root@centos8 ~]# df | awk -F' +|%' '/^\/dev.*/{print $1"\t"$5}'
/dev/nvme0n1p2 7
/dev/nvme0n1p3 1
/dev/nvme0n1p1 17
# 还是一样 只不过写法 跟上面 略微有些不同而已
[root@centos8 ~]#awk -v FS=":" '{print $1FS$3}' /etc/passwd |head -n3
root:0
bin:1
daemon:2
#awk可以调用系统变量
awk 例子的注意事项
df | awk -F' +|%' '/^\/dev.*/{print $1"\t"$5}'
/dev/nvme0n1p2 7
/dev/nvme0n1p3 1
/dev/nvme0n1p1 17
df | awk -F'[ %]+' '/^\/dev.*/{print $1"\t"$5}'
/dev/nvme0n1p2 7
/dev/nvme0n1p3 1
/dev/nvme0n1p1 17
[root@centos8 ~]# cat haha
1 www.magedu.com
2 blog.magedu.com
3 study.magedu.com
4 linux.magedu.com
5 python.magedu.com
[root@centos8 ~]# awk -F '[ +.]' '{print $2}' haha
www
blog
study
linux
python
[root@centos8 ~]# awk -F'[ .]+' '{print $2}' haha
www
blog
study
linux
python
[root@centos8 ~]# awk -F ' +|.' '{print $2}' haha
[root@centos8 ~]# awk -F ' +|\\.' '{print $2}' haha
www
blog
study
linux
python
# "." 可能被认为是正则表达式了 正则表达式里 "."表示任意单个字符, 放到上面的例子里,"."匹配到最后一个字符,所以$2 是空?
浙公网安备 33010602011771号