awk用法解析(macos环境BSD shell)

参考:
https://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html

简介

awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。

awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

使用方法

awk ‘{pattern + action}’ {filenames}
尽管操作可能会很复杂,但语法总是这样,其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。

awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。

通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。


test.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
root:x:0:0:root:/root:/bin/zsh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/cache/rpcbind:/sbin/nologin
rtkit:x:499:497:RealtimeKit:/proc:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
saslauth:x:498:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
pulse:x:497:496:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
stonelinux:x:500:500:StoneParkLinux:/home/stonelinux:/bin/zsh

全局设置(测试)

1
file=test.txt

调用awk

有三种方式调用awk

1.命令行方式

1
2
3
awk [-F  field-separator]  'commands'  input-file(s)

awk -F: '/root/{print $7}' $file

其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格

2.shell脚本方式
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk

1
2
3
4
5
6
7
8
#------------------------------
# commandfile.sh文件内容
#!/bin/awk
##/root/{print $7}
#/root/
#------------------------------

awk -F: -f ./commandfile.sh $file

3.将所有的awk命令插入一个单独文件,然后调用:

1
2
3
awk -f awk-script-file input-file(s)

awk -F: -f ./commandfile.sh $file

其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。


入门实例

1
last -5 | awk '{print $1}'
1
awk工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 "[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推。
1
2
3
4
5
6
7
8
9
cat $file |awk  -F ':'  '{print $1}'  

#结果
root
bin
daemon
adm
lp
sync

这种是awk+action的示例,每行都会执行action{print $1}。
-F指定域分隔符为’:’。


如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割

1
2
3
4
5
6
7
cat $file | awk  -F ':' '{print $1"\t"$7}'
root /bin/zsh
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync

awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。

awk直接修改原文件

1
2
#注意:重定向符号后面的文件名需要加双引号
cat $file |awk -F ':' '{print $1"\t"$7 > "aa/a.txt"}'

awk + regex

搜索$file有root关键字的所有行

1
awk -F: '/root/' $file

这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。

搜索支持正则,例如找root开头的:

1
awk -F: '/root/{print $7}' $file # 这里指定了action{print $7}


awk内置变量

awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。

1
2
3
4
5
6
7
8
9
10
11
ARGC               命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符

此外,$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。


统计$file:文件名,每行的行号,每行的列数,对应的完整行内容:

1
awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' $file

使用printf替代print,可以让代码更加简洁,易读

1
awk  -F ':'  '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' $file

print和printf
awk中同时提供了print和printf两种打印输出的函数。

其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。

printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。

awk编程

除了awk的内置变量,awk还可以自定义变量。
下面统计/etc/passwd的账户人数

1
2
3
4
5
6
7
awk '{
count++;
print $0;
}
END{
print "user count is ", count
}' $file

count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以;号隔开

这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0:

1
2
3
4
5
6
7
8
9
10
11
12
awk '
BEGIN {
count=0;
print "[start]user count is ", count
} {
count=count+1;
print $0;
}
END{
print "[end]user count is ", count
}
' $file

统计某个文件夹下的文件占用的字节数

1
2
3
4
5
6
7
8
9
ls -l $temp | awk '
BEGIN {
size=0;
} {
size=size+$5;
}
END {
print "[end]size is ", size
}'

如果以M为单位显示:

1
ls -l $temp|awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}'

注意,统计不包括文件夹的子目录。

条件语句

awk中的条件语句是从C语言中借鉴来的,见如下声明方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if (expression) {
statement;
statement;
... ...
}

if (expression) {
statement;
} else {
statement2;
}

if (expression) {
statement1;
} else if (expression1) {
statement2;
} else {
statement3;
}

统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹):

1
ls -l $temp |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'

循环语句

awk中的循环语句同样借鉴于C语言,支持while、do/while、for、break、continue,这些关键字的语义和C语言中的语义完全相同。

数组

因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
awk -F ':' '
BEGIN {
count=0;
} {
name[count] = $1;
count++;
}
END {
for (i = 0; i < NR; i++) {
print i, name[i]
print "hello world"
}

}' $file
1
2
3
4
5
6
7
8
9
10
11
12
13
#结果
0 root
hello world
1 bin
hello world
2 daemon
hello world
3 adm
hello world
4 lp
hello world
5 sync
hello world

这里使用for循环遍历数组

awk编程的内容极多,这里只罗列简单常用的用法,更多请参考 http://www.gnu.org/software/gawk/manual/gawk.html


awk之RS、ORS与FS、OFS

参考:
https://www.cnblogs.com/fhefh/archive/2011/11/16/2251656.html

1
2
3
4
5
6
7
8
9
RS:Record Separator,记录分隔符

ORS:Output Record Separate,输出当前记录分隔符

FS:Field Separator,字段分隔符

OFS:Out of Field Separator,输出字段分隔符

PS:RS、ORS、FS、OFS的英文解释绝不是这样的,这里只是解释清楚。建议去阅读awk的英文读物,其中解释了缩写的含义。

什么是field(字段),什么是record(记录行)?

示例:
1.txt

1
2
3
1. i am a student.
2. i like to swim
3. hello moto

1代表第一个记录行,2代表第二个记录行,3代表第三个记录行。通过观察我们可以知道总共有3个记录行(record)。

看看第一行:“i am a student”,这一行的每个单词都是一个字段(field)。“i”是一个字段,“am”是一个字段,“a”是一个字段,“student”是一个字段,该行总共有4个字段。

RS与ORS

1
2
3
4
5
6
7
2.txt

a\n
b\n
c\n
d\n
e\n

该文本总共有5行,每一行都有一个换行符“\n”。所以每行记录都是以“\n”为一个(换行的)标志。

5行变1行(ORS:Output Record Separate, 输出的时候, 行分隔符 替换成 指定分隔符)

观察每一行的“换行符号”,然后将“换行符号”替换成你想要的符号。

1
2
3
awk 'BEGIN{ORS="|"}{print $0}' 2.txt | sed -n "s/\\\n//gp" | sed -n 's/.$//p' 

#.表示任意 $结束符 匹配到了 最后一个 ,(逗号) 然后替换成空
1
2
3
3.txt

a|b|c|d|e

1行变5行(RS:Record Separator 读取的时候, 指定行分隔符,用指定分隔符 切成行)

找到某某标志,让每个某某后的内容重新变成一行

1
awk 'BEGIN{RS="|"}1' 3.txt

FS:字段分隔符

FS默认值为“ (空格)”,如“hello moto”.
在“hello moto”中有一个空格,空格就是hello与moto的分隔符(separator),而hello与moto就为字段(fields)。awk以空格来区分。

1
2
# 在看看“i----love----you”,如果我们用命令
awk '{ print $1 }'

”会看到结果为:

1
i----love----you

1
2
3
4
5
6
#如果想打印出三个字母,通过观察可发现“----”为分隔符。

awk 'BEGIN{ FS="----";}{ print $1,$2,$3 }' filename

# 结果
# i love you

OFS:输出的字段分隔符。

这么解释吧,如上例中“i—-love—-you”,“—-”为分隔符(FS),如果我们想改为用其他符号显示可以这样:

1
2
3
awk 'BEGIN{ FS="----";OFS="*****" }{ print $1,$2,$3 }' filename

i*****love*****you

其实OFS还有一个例子

1
2
3
echo "abc" | awk '{ OFS="." } { NF=NF; print NF,$0}'
# 结果
# 1.abc

1
2
3
4
5
6
7
echo "abc" | awk 'BEGIN{ OFS="." } { print $0,"hello","world"}' # abc.hello.world
echo "abc" | awk 'BEGIN{ OFS="." } { print $0 "hello" "world"}' # abchelloworld
echo "abc" | awk 'BEGIN{ OFS="." } { print $0"hello""world"}' # abchelloworld

echo "abc" | awk '{ print $0,"hello","world"}' # abc hello world 没有指定OFS 默认是空格

# 总结, 还有用,(逗号)来写 print的分割, 指定OFS来完成指定列分隔符

PS:RS与ORS可以说成是一个互逆的过程(↔)也可以看成一个替换的过程,但是看成互逆的过程比较好理解;FS与OFS就是一个替换的过程。


###为什么awk中的“1”打印当前行?
https://stackoverflow.com/questions/20262869/why-does-1-in-awk-print-the-current-line

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cat file
a b c d e f
1 2 3 4

不输出后两列字段,代码如下
awk '{NF=NF-2}1'
file
a b c d
1 2

{NF=NF-2}1,这个后面接的1是什么意思呢?
#----------------------------------
awk是 一组 pattern action, pattern action, ……的组合
pattern能匹配上,就执行对应的action。
pattern省略或为1,等价于 /.*/
action省略,等价于 { print }
所以上式的完整写法是:
/.*/ {NF=NF-2}
/.*/ {print}
因为两个pattern相同,所以可以合并:
/.*/ {NF=NF-2; print;}
1
2
3
4
5
6
7
8
9
10
11
12
#shell去掉最后一个字符
#原创 2016年07月15日 11:34:55 8196
#387691,387710,387720,387817,387922,388067,
#如何搞掉最后一个,? 简单快捷的?

sed 's/.$//'

awk '{sub(/.$/,"")}1'

awk '{printf $0"\b \n"}' ufile

#\b Backspace, Control-h, ASCII code 8 (BS).

参考:
ftp://ftp.gnu.org/old-gnu/Manuals/gawk-3.0.3/html_chapter/gawk_5.html


awk内建变量示例详解之NR、FNR、NF

参考:
http://www.letuknowit.com/topics/20120329/sample-about-awk-build-in-variable-nr-fnr-nf.html/

Number of Record

NR表示从awk开始执行后,按照记录分隔符读取的数据次数,默认的记录分隔符为换行符,因此默认的就是读取的数据行数,NR可以理解为Number of Record的缩写。

File Number of Record

在awk处理多个输入文件的时候,在处理完第一个文件后,NR并不会从1开始,而是继续累加,因此就出现了FNR,每当处理一个新文件的时候,FNR就从1开始计数,FNR可以理解为File Number of Record。

Number of Field(用FS切,默认是空格, 切出来几块)

NF表示目前的记录被分割的字段的数目,NF可以理解为Number of Field。

1
2
3
4
5
class1.txt

zhaoyun 85 87
guanyu 87 88
liubei 90 86
1
2
3
4
class2.txt

caocao 92 87 90
guojia 99 96 92
1
2
3
4
5
6
printf 'zhaoyun 85 87
guanyu 87 88
liubei 90 86' > class1.txt

printf 'caocao 92 87 90
guojia 99 96 92' > class2.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 现在要查看两个班级的所有成绩信息,并在每条信息前加上行号,则可以使用下面的awk指令;
awk '{print NR,$0}' class1.txt class2.txt
1 zhaoyun 85 87
2 guanyu 87 88
3 liubei 90 86
4 caocao 92 87 90
5 guojia 99 96 92
# 这里的行号就是通过NR来实现的,awk每读取一条记录,NR的值便加一。如果要求每个班级的行号从头开始变化,则需要使用FNR来实现,如下:
awk '{print FNR,$0}' class1.txt class2.txt
1 zhaoyun 85 87
2 guanyu 87 88
3 liubei 90 86
1 caocao 92 87 90
2 guojia 99 96 92
# 下面的示例结合awk内建变量FILENAME,显示出来的两个班级的成绩信息可以进行更好的区分;
awk '{
fn=FILENAME"\b\b\b\b";
print fn,"第"NR"条记录",fn"的第"FNR"条记录","最后一个字段为"$NF;
}' class1.txt class2.txt
class1 第1条记录 class1的第1条记录 最后一个字段为87
class1 第2条记录 class1的第2条记录 最后一个字段为88
class1 第3条记录 class1的第3条记录 最后一个字段为86
class2 第4条记录 class2的第1条记录 最后一个字段为90
class2 第5条记录 class2的第2条记录 最后一个字段为92
# 除了NR和FNR外,上面的示例中还演示了NF的使用,class1中每行有3个字段,而class2中有4个字段,通过$NF就可以很方便的获取最后一个字段了。

awk next命令

参考:
https://linux.cn/article-7609-1-rel.html

food_list.txt

1
2
3
4
5
6
7
printf 'No      Item_Name               Price           Quantity
#1 Mangoes $3.45 5
#2 Apples $2.45 25
#3 Pineapples $4.45 55
#4 Tomatoes $3.45 25
#5 Onions $1.45 15
#6 Bananas $3.45 30' > food_list.txt

next 命令帮助你阻止运行命令执行过程中多余的步骤。
awk 跳过你所提供的所有剩下的模式和表达式,直接处理下一个输入行。

运行下面的命令,它将在每个食物数量小于或者等于 20 的行后面标一个星号:

1
2
3
4
5
6
7
8
# awk '$4 <= 20 { printf "%s\t%s\n", $0,"*" ; } $4 > 20 { print $0 ;} ' food_list.txt 
No Item_Name Price Quantity
1 Mangoes $3.45 5 *
2 Apples $2.45 25
3 Pineapples $4.45 55
4 Tomatoes $3.45 25
5 Onions $1.45 15 *
6 Bananas $3.45 30

上面的命令实际运行如下:

1
2
3
4
5
6
7
首先,它用$4 <= 20表达式检查每个输入行的第四列(数量(Quantity))是否小于或者等于 20,如果满足条件,它将在末尾打一个星号 (*)。
接着,它用$4 > 20表达式检查每个输入行的第四列是否大于20,如果满足条件,显示出来。


但是这里有一个问题, 当第一个表达式用{ printf "%s\t%s\n", $0,"**" ; }命令进行标注的时候在同样的步骤第二个表达式也进行了判断这样就浪费了时间.

因此当我们已经用第一个表达式打印标志行的时候就不再需要用第二个表达式$4 > 20再次打印。

要处理这个问题, 我们需要用到next 命令:

1
2
3
4
5
6
7
8
# awk '$4 <= 20 { printf "%s\t%s\n", $0,"*" ; next; } $4 > 20 { print $0 ;} ' food_list.txt
No Item_Name Price Quantity
1 Mangoes $3.45 5 *
2 Apples $2.45 25
3 Pineapples $4.45 55
4 Tomatoes $3.45 25
5 Onions $1.45 15 *
6 Bananas $3.45 30
1
当输入行用$4 <= 20 { printf "%s\t%s\n", $0,"*" ; next ; }命令打印以后,next命令将跳过第二个$4 > 20 { print $0 ;}表达式,继续判断下一个输入行,而不是浪费时间继续判断一下是不是当前输入行还大于 20

next命令在编写高效的命令脚本时候是非常重要的,它可以提高脚本速度。


awk, 批量改名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ls F* M* | awk '{
#
# first = substr($1, 1, 1);
# print first;
# suffix = substr($1, 2);
# print suffix;
# if (first == "M") {
# newfile = "ic_male_head0"suffix;
# } else {
# newfile = "ic_female_head0"suffix;
# }
# system("mv "$1" "newfile);
#
#}'

#ls *.jpg | awk 'BEGIN {count=0} {
#
# suffix = substr($1, 1);
#
# count+=1
#
# newfile = count"""img.jpg"
#
# system("mv "$1" "newfile);
#
#}'

ls *.png | awk 'BEGIN {count=0;} {

suffix = substr($0, 1);

count+=1;

newfile="img"count".png";

system("mv "$0" "newfile);

print suffix;
}'
# 解决不了带特殊字符的文件

awk 条件操作符:

参考:
https://www.cnblogs.com/benevolencedoctor/p/5181203.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# condition_test.txt

FIRST_FIELD SECOND_FIELD THIRD_FIELD FORTH_FIELD FIFTH_FIELD SIXTH_FIELD SEVENTH_FIELD EIGHTH_FIELD NINTH_FIELD TENTH_FIELD
expect1 2 3 4 5 6 7 8 9 10
expect2 2 48 4 5 6 7 8 9 10
expect3 2 48 4 5 6 7 8 9 10
asima 2 48 4 5 6 7 8 9 10
asima 2 48 4 5 6 7 8 9 10

11 22 33 44 55 66 77 88 99 1010

The high construction is also one kind of artware,
is classical,
is graceful,
looks like a rich paint color painting!
everywhere is filling the Green,
is also fluttering including the air green grass taste all around green and glossy,
the Green startled colorful, the windmill also stops down,
is infatuated with in the beautiful scene ......

高高的建筑也是一种艺术品,古典、优雅,像一幅浓郁的油漆彩画!
到处弥漫着绿色,连空气也飘着青草味
四周一片绿油油,绿色的惊艳,风车也停下来,陶醉在美景中……

Apple Phone

a b c d e f g h i j k l m n o p q r s t u v w x y z
b c d e f g h i j k l m n o p q r s t u v w x y z a

b c d e f g h i j k l m n o p q r s t u v w x y z a=1

stone 25 man 1985/01/17 China Beijing

asima stone 25 man 1985/01/17 China Beijing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/bin/bash

#touch condition_test.txt
#subl condition_test.txt
file="condition_test.txt"
#第一字域,包含expect,就打印整行
awk '{if($1~/expect/) print $0}' $file
#echo "first, second, third,forth,fifth,sixth,seventh,eighth,ninth,tenth" | sed -E -e 's/[, ,]/ /g' | tr -s ' '
#tr 'a-z' 'A-Z' < $file
awk '$1~/expect/{print $0}' $file

#精确匹配:,只打印第3 域等于"48"的记录
awk '$3=="48" {print $0}' $file
#
#
#不等于:
awk '$1 != "asima"' $file
#
#
#不匹配: 打印整条不包含ASIMA 的记录
awk '$0 !~ /asima/' $file # ~ 匹配正则表达式的意思
#
#
#小于:
awk '{
if ($1 !~ /[0-9]/) {
next; #如果不包含数字 就别再匹配下面的条件了
}
} {
if ($1<$2) print $1,"is smaller"
}' $file

awk '{
if ($1 ~ /^[0-9]+/) {
#如果不包含数字 就别再匹配下面的条件了
if ($1<$2) {
print $1,"is smaller"
}
}
}' $file
#
#
#设置大小写: awk '/[Gg]reen/' temp 打印整条包含Green,或者green 的记录
awk '/[Gg]reen/{print NR,$0}' $file
#
#
#任意字符: awk '$1 ~/^...a/' temp 打印第1 域中第四个字符是a 的记录,符号’^’
#代表行首,符合’.’代表任意字符
awk '$1 ~/^...l/' $file
#
#
#AND 与关系: awk '{if ( $1=="a" && $2=="b" ) print $0}' temp
awk '{if ( $1=="a" && $2=="b" ) print $0}' $file
#
#
#OR 或关系: awk '{if ($1=="a" || $1=="b") print $0}' temp
awk '{if ($1=="a" || $1=="b") print $0}' $file
#
#
#for循环
#awk -F " " '{
# for (i=1;i<=NF;i++){
# if($i~/a=/) {
# print $i
# }
# }
#}' $file

awk '/[Gg]reen/{
for (i=1;i<=NF;i++){
if($i~/[Gg]reen/) {
print FNR,$i
}
}
}' $file

NF 的另一用法: echo $PWD | awk -F/ '{print $NF}' 显示当前目录名