系列目录与参考文献传送门: shell入门学习笔记-序章
变量名 | 速记 | 描述 |
---|---|---|
FS | File Separator | 输入字段分隔符,默认是空格或制表符 |
OFS | Output File Separator | 输出字段分隔符,默认是空格 |
RS | Row Separator | 输入记录分隔符,默认是换行符\n |
ORS | Output Row Separator | 输出记录分隔符,默认是换行符\n |
NF | Number of Fields | 统计当前记录中字段个数 |
NR | Number of current Row | 统计记录编号,每处理一行记录,编号就会+1 |
FNR | in current File, the Number of current Row | 统计记录编号,每处理一行记录,编号也会+1, 与NR不同的是,处理第二个文件时,编号会重新计数。 |
ARGV | ARGument Array | 命令行参数数组序列数组,下标从0开始,ARGV[0]是awk |
ARGC | ARGument Count | 命令行参数数量 |
ARGIND | ARGument INDex | 当前正在处理的文件索引值。第一个文件是1,第二个文件是2,以此类推 |
ENVIRON | ENVIRONment variables | 当前系统的环境变量 |
FILENAME | FILENAME for current file | 输出当前处理的文件名 |
IGNORECASE | IGNORECASE | 忽略大小写 |
SUBSEP | arrays’s SUBscripts’s SEParates | 数组中下标的分隔符,默认为"\034" |
在之前的章节,学习过以-F fs
设置输入字段的分隔符。
# 格式化打印时间
admindeMacBook-Pro:~ admin$ echo "12:28:59" |awk -F':' '{print $1"时"$2"分"$3"秒"}'
12时28分59秒
上面的功能功能也可以通过下面的命令实现:
# 格式化打印时间
admindeMacBook-Pro:~ admin$ echo "12:28:59" |awk 'BEGIN{FS=":"}{print $1"时"$2"分"$3"秒"}'
12时28分59秒
admindeMacBook-Pro:~ admin$ echo "12:28:59" |awk -vFS=':' '{print $1"时"$2"分"$3"秒"}'
12时28分59秒
FS
可以放在BEGIN
模块中设置。FS
可以通过-vVar=value
设置。FS
可以通过-F fs
设置。同理,对于输出分隔符,也有以下操作:
# 格式化打印时间
admindeMacBook-Pro:~ admin$ echo "12:28:59" |awk 'BEGIN{FS=":";OFS="-"}{print $1,$2,$3}'
12-28-59
admindeMacBook-Pro:~ admin$ echo "12:28:59" |awk -vFS=':' -vOFS='-' '{print $1,$2,$3}'
12-28-59
admindeMacBook-Pro:~ admin$ echo "12:28:59" |awk -vFS=':' '{print $1"-"$2"-"$3}'
12-28-59
OFS
可以在BEGIN
模块中设置。OFS
可以通过-vVar=value
设置。OFS
可以通过手动拼接字符串"str"
实现。``RS和
ORS与
FS和
OFS`的用法类型,举例如下:
admindeMacBook-Pro:~ admin$ echo "A-B-C" | awk 'BEGIN{RS="-"}{print $0}'
A
B
C
admindeMacBook-Pro:~ admin$ echo "A-B-C" | awk -vRS='-' '{print $0}'
A
B
C
admindeMacBook-Pro:~ admin$ echo "A-B-C" | awk -vRS='-' -vORS=',' '{print $0}'
A,B,C
admindeMacBook-Pro:~ admin$ echo "A-B-C" | awk 'BEGION{RS="-";ORS=","}{print $0}'
A-B-C
# NF即当前行字段数量
admindeMacBook-Pro:~ admin$ echo "a b c" |awk '{print NF}'
3
# $NF即最后一个字段
admindeMacBook-Pro:~ admin$ echo "a b c" |awk '{print $NF}'
c
# $(NF-1)即倒数第二个字段
admindeMacBook-Pro:~ admin$ echo "a b c" |awk '{print $NF-1}'
-1
admindeMacBook-Pro:~ admin$ echo "a b c" |awk '{print $(NF-1)}'
b
# ${number}=""可以排除某个字段
admindeMacBook-Pro:~ admin$ echo "a b c" |awk '{print $0}'
a b c
admindeMacBook-Pro:~ admin$ echo "a b c" |awk '$1=""{print $0}'
admindeMacBook-Pro:~ admin$ echo "a b c" |awk '$1="";{print $0}'
b c
admindeMacBook-Pro:~ admin$ echo "a b c" |awk '$NF="";{print $0}'
a b
admindeMacBook-Pro:~ admin$ echo "a b c" |awk '$(NF-1)="";{print $0}'
a c
admindeMacBook-Pro:~ admin$ seq 3 |sed 's/.*/name&/'
name1
name2
name3
# 通过NR打印行号
admindeMacBook-Pro:~ admin$ seq 3 |sed 's/.*/name&/' |awk '{print NR,$0}'
1 name1
2 name2
3 name3
# 通过END{print NR}打印总行数
admindeMacBook-Pro:~ admin$ seq 3 |sed 's/.*/name&/' |awk 'END{print NR}'
3
# 通过NR=number打印指定行
admindeMacBook-Pro:~ admin$ seq 3 |sed 's/.*/name&/' |awk 'NR==2'
name2
# 打印指定行的指定列
admindeMacBook-Pro:~ admin$ seq 3 |sed 's/.*/name&/;s/.*/& male/'
name1 male
name2 male
name3 male
admindeMacBook-Pro:~ admin$ seq 3 |sed 's/.*/name&/;s/.*/& male/' |awk 'NR==1{print $1}'
name1
# 通过NR>number/NR=2{print NR,$1}'
2 name2
3 name3
# FNR与NR的区别
admindeMacBook-Pro:myshell admin$ cat m.txt
m1
m2
m3
admindeMacBook-Pro:myshell admin$ cat n.txt
n1
n2
n3
admindeMacBook-Pro:myshell admin$ awk '{print "单个文件第"FNR"行,总计第"NR"行: ",$0}' m.txt n.txt
单个文件第1行,总计第1行: m1
单个文件第2行,总计第2行: m2
单个文件第3行,总计第3行: m3
单个文件第1行,总计第4行: n1
单个文件第2行,总计第5行: n2
单个文件第3行,总计第6行: n3
admindeMacBook-Pro:~ admin$ cat m.txt
m1
m2
m3
admindeMacBook-Pro:~ admin$ cat n.txt
n1
n2
admindeMacBook-Pro:~ admin$ awk '{print "当前第"ARGIND"个文件,第"FNR"行,总记第"NR"行,内容是:",$0}' m.txt n.txt
当前第1个文件,第1行,总记第1行,内容是: m1
当前第1个文件,第2行,总记第2行,内容是: m2
当前第1个文件,第3行,总记第3行,内容是: m3
当前第2个文件,第1行,总记第4行,内容是: n1
当前第2个文件,第2行,总记第5行,内容是: n2
admindeMacBook-Pro:~ admin$ awk '{if(ARGIND==1){print "处理m.txt,第"FNR"行:",$0} if(ARGIND==2){print "处理n.txt,第"FNR"行:",$0}}' m.txt n.txt
处理m.txt,第1行: m1
处理m.txt,第2行: m2
处理m.txt,第3行: m3
处理n.txt,第1行: n1
处理n.txt,第2行: n2
# ARGC和ARGV用在BEGIN模块中
admindeMacBook-Pro:~ admin$ awk '{print ARGC}'
^C
admindeMacBook-Pro:~ admin$ awk '{print ARGV[0]}'
^C
# ARGV下标从0开始
admindeMacBook-Pro:~ admin$ awk 'BEGIN{print ARGC}'
1
admindeMacBook-Pro:~ admin$ awk 'BEGIN{print ARGV[0]}'
awk
admindeMacBook-Pro:~ admin$ awk 'BEGIN{print ARGV[1]}'
admindeMacBook-Pro:~ admin$ awk 'BEGIN{print ARGC}' 1
2
admindeMacBook-Pro:~ admin$ awk 1 'BEGIN{print ARGC}' 1
awk: can't open file BEGIN{print ARGC}
source line number 1
admindeMacBook-Pro:~ admin$ awk 'BEGIN{print ARGC}' 1 2
3
admindeMacBook-Pro:~ admin$ awk 'BEGIN{print ARGV[2]}' 1 2
2
ARGC
和ARGV
用在BEGIN
模块中。ARGV
下标从0
开始,ARGV[0]=awk
,ARGV[1]
是第一个参数。# 在BEGIN模块中使用ENVIRON
admindeMacBook-Pro:~ admin$ awk '{print ENVIRON["HOME"]}'
^C
admindeMacBook-Pro:~ admin$ awk 'BEGIN{print ENVIRON["HOME"]}'
/home/hanchao
# 环境变量需要export
admindeMacBook-Pro:~ admin$ aaaaa=123456
admindeMacBook-Pro:~ admin$ echo $aaaaa
123456
admindeMacBook-Pro:~ admin$ awk 'BEGIN{print ENVIRON["aaaaa"]}'
admindeMacBook-Pro:~ admin$ export aaaaa
admindeMacBook-Pro:~ admin$ awk 'BEGIN{print ENVIRON["aaaaa"]}'
123456
ENVIRON
需要在BEGIN
模块中使用。ENVIRON
只针对环境变量,关于环境变量,请参考之前的作用域
章节。admindeMacBook-Pro:~ admin$ awk '{if(ARGIND==1){print "m.txt",$0} if(ARGIND==2){print "n.txt",$0}}' m.txt n.txt
m.txt m1
m.txt m2
m.txt m3
n.txt n1
n.txt n2
admindeMacBook-Pro:~ admin$ awk '{print FILENAME,$0}' m.txt n.txt
m.txt m1
m.txt m2
m.txt m3
n.txt n1
n.txt n2
FILENAME
打印的是当前
正在处理的文件。运算符 | 描述 |
---|---|
(....) |
分组 |
$ |
字段引用 |
++ -- |
一元运算符:递增和递减 |
+ - |
一元运算符:取正,取负。负负为正。 |
+ - * / % ^ |
二元运算符:加减乘除、取余和幂 |
< > <= >= != == |
关系运算符 |
= += -= *= /= %= ^= |
变量赋值运算符 |
&& || ! |
逻辑运算符:逻辑与 逻辑或 逻辑否定 |
expr1 ? expr2 : expr3 |
三元运算符:条件表达式,如果expr1为真,则执行expr2,否则执行expr3 |
var~// var!~// |
正则表达式匹配,否定正则表达式匹配 |
in |
数组成员 |
| |
管道,用于getline,print和printf |
0
。空
。0
空
admindeMacBook-Pro:~ admin$ awk 'BEGIN{num=0;if(!num) print "0 is false";
> str="";if(!str) print "blank is false";
> if(!unk) print "unknown is false"}'
0 is false
blank is false
unknown is false
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=1;b=2;c=3;d=a+b*c;print d}'
7
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=1;b=2;c=3;d=(a+b)*c;print d}'
9
admindeMacBook-Pro:~ admin$ echo "aa bb" |awk '{print $0}'
aa bb
admindeMacBook-Pro:~ admin$ echo "aa bb" |awk '{print $1}'
aa
admindeMacBook-Pro:~ admin$ echo "aa bb" |awk '{print $2}'
bb
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=2;print a;print a++;print a--}'
2
2
3
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=2;print a;print ++a;print --a}'
2
3
2
# 取正与取负
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=1;b=-2;print -a;print -b;}'
-1
2
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=1;b=-2;print +a;print +b;}'
1
-2
# 只能位于变量之前
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=1;b=-2;print a+;print b+;}'
awk: cmd. line:1: BEGIN{a=1;b=-2;print a+;print b+;}
awk: cmd. line:1: ^ syntax error
awk: cmd. line:1: BEGIN{a=1;b=-2;print a+;print b+;}
awk: cmd. line:1: ^ syntax error
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=1;b=-2;print a-;print b-;}'
awk: cmd. line:1: BEGIN{a=1;b=-2;print a-;print b-;}
awk: cmd. line:1: ^ syntax error
awk: cmd. line:1: BEGIN{a=1;b=-2;print a-;print b-;}
awk: cmd. line:1: ^ syntax error
#可以用于获取字符串变量中的数值
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=11b;print +a}'
11
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=11b;print -a}'
-11
admindeMacBook-Pro:~ admin$ echo "11ww" |awk '{print +$0}'
11
admindeMacBook-Pro:~ admin$ echo "11ww22" |awk '{print +$0}'
11
+
和-
在作为一元运算符时,需要放在变量之前。+var
:表示(+1) * var
-var
:表示(-1) * var
+
和-
可以用于获取字符串变量中的数值,但仅限于首个数值。+
不会改变量的正负:正正得正,正负得负。-
会改变变量的正负:负正得负,负负得正。awk支持,加减乘除和取余,即:+
-
*
/
%
^
。
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=1;b=2;c=3;d=4;print a+b-c*d;print 3%2;}'
-9
1
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=3;print a^2}'
9
通过%
对应奇偶行
admindeMacBook-Pro:~ admin$ seq 6 |awk '$0%2==1{print $0}'
1
3
5
admindeMacBook-Pro:~ admin$ seq 6 |awk '$0%2==0{print $0}'
2
4
6
awk支持的关系运算符为:<
>
<=
>=
!=
==
。
admindeMacBook-Pro:~ admin$ awk 'BEGIN{if(1==1 && 1!=2) print "1==1 && 1!=2"}'
1==1 && 1!=2
admindeMacBook-Pro:~ admin$ awk 'BEGIN{if(2>=1 && 1<2) print "2>=1 && 1<2"}'
2>=1 && 1<2
awk支持变量赋值运算符,即:=
+=
-=
*=
/=
%=
^=
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=1;a+=1;b=2;b-=2;c=3;c*=3;d=4;d/=4;e=5;e%=5;print a,b,c,d,e}'
2 0 9 1 0
admindeMacBook-Pro:~ admin$ awk 'BEGIN{a=3;a^=2;print a}'
9
awk支持逻辑运算符,即:逻辑与&&
,逻辑或||
,逻辑非!
admindeMacBook-Pro:~ admin$ awk 'BEGIN{if(1 && 2) print "true"}'
true
admindeMacBook-Pro:~ admin$ awk 'BEGIN{if(0 || 1) print "true"}'
true
admindeMacBook-Pro:~ admin$ awk 'BEGIN{if(!0) print "true"}'
true
admindeMacBook-Pro:~ admin$ seq 9 11 |awk '/1/{print $0}'
10
11
admindeMacBook-Pro:~ admin$ seq 9 11 |awk '!/1/{print $0}'
9
通过!
打印奇数行和偶数行
admindeMacBook-Pro:~ admin$ echo good |awk '0'
admindeMacBook-Pro:~ admin$ echo good |awk '1'
good
admindeMacBook-Pro:~ admin$ echo good |awk 'a=0;a'
admindeMacBook-Pro:~ admin$ echo good |awk 'a=1;a'
good
good
# 奇数行
admindeMacBook-Pro:~ admin$ seq 6 |awk 'i=!i'
1
3
5
# 偶数行
admindeMacBook-Pro:~ admin$ seq 6 |awk '!(i=!i)'
2
4
6
awk '0'
:因为0
表示false,不会打印任何信息。awk '1'
:因为1
表示true,会打印当前行。awk 'a=1'
:等价于awk 'a'
,因为a=1,所以条件为真,会打印当前行。关于seq 6 |awk 'i=!i'
的解析:
i=!i
==>i=!0
,即i=1
,条件为真,打印第一行。i=1
。此时i=!i
,则i=0
,条件为false,不打印第2行。admindeMacBook-Pro:~ admin$ awk 'BEGIN{print 1?1:2}'
1
替换换行符为空格
admindeMacBook-Pro:~ admin$ seq 3 |awk '{n=(n?n" "$0:$0)}END{print n}'
1 2 3
n=(n?n" "$0:$0)
,因为n
初始化为0
,所以,最终n=$0
==> n=1
n=(n?n" "$0:$0)
,因为n=1
,所以n=n" "$0
==> n=2 1
每两行后面新增一行
admindeMacBook-Pro:~ admin$ seq 5 |awk '{print NR%2?$0:$0"\n----"}'
1
2
----
3
4
----
5
每三行合并为一行
admindeMacBook-Pro:~ admin$ seq 6 |awk '{printf NR%3?$0" ":$0"\n"}'
1 2 3
4 5 6
admindeMacBook-Pro:~ admin$ echo "123hah 999kk" |awk '$0~/12/{print $0}'
123hah 999kk
admindeMacBook-Pro:~ admin$ echo "123hah 999kk" |awk '$1~/12/{print $0}'
123hah 999kk
admindeMacBook-Pro:~ admin$ echo "123hah 999kk" |awk '$2~/12/{print $0}'
admindeMacBook-Pro:~ admin$ echo "123hah 999kk" |awk '$2~/99/{print $0}'
123hah 999kk
admindeMacBook-Pro:~ admin$ echo "123hah 999kk" |awk '$2!~/99/{print $0}'
admindeMacBook-Pro:~ admin$ echo "123hah 999kk" |awk '$2!~/12/{print $0}'
123hah 999kk
var~//
和var!~//
admindeMacBook-Pro:~ admin$ awk 'BEGIN { arr[0] = 1; arr[1] = 2; arr[2] = 3; for (i in arr) print i}'
0
1
2
admindeMacBook-Pro:~ admin$ seq 5
1
2
3
4
5
admindeMacBook-Pro:~ admin$ seq 5|shuf
2
5
1
4
3
admindeMacBook-Pro:~ admin$ seq 5|shuf
1
2
5
3
4
admindeMacBook-Pro:~ admin$ seq 5|shuf|awk '{print $0 |"sort"}'
1
2
3
4
5
shuf
:把输入行随机输出。