Linux 学习之awk的使用
awk学习
这个笔记主要是借鉴了朱双印老师的笔记,经过我自己的整理和思考而写成的。可能会有一些疏漏之处,希望读者能够不吝指出。
第一次用Markdown转html,不知道效果如何。
Index
基础语法
基本形式: awk ‘模式{方法}’ 文件
变量
变量规定了一些awk的选项,有识别的时候起作用的变量,有输出的时候的变量,也有一些文档内部的内容相关的变量。 用户也可以自定义变量,用作其他的控制用途。
- 变量的传入方法:
- 根据所谓的“选项”来设置变量:
- -F# 表示以#来作为读取文件的时候的分隔符,对应明文设置变量的FS
- 在选项中明文定义或设置变量:
awk -v FS='#'既是把输入文本的时候的分隔符设置为#
- 在花括号内,即在"方法"内部定义或者设置变量:
awk 'BEGIN{ FS='#'; print FS}'即可在读取文件之前把FS设置成需要的值
- 根据所谓的“选项”来设置变量:
- 常见的内置的变量一览
- FS 输入字段分隔符,默认为空白字符#注意不是空字符#
- OFS 输出字段分隔符,默认为空白字符
- RS 输入记录分隔符,默认问换行符
- ORS 输出记录分隔符,默认换行符
- NF number of field,当前行的字段的个数,即被分割成了几列
- NR 行号,当前处理的文本行的行号
- FNR 各个文件分别计数的行号
- FILENAME 当前文件的文件名字
- ARGC 命令行参数的个数
- ATGV 数组,保存的是命令行所给定的各个参数
- 使用的注意事项:
- 需要打印输出的时候,要像shell的语法一样,需要用$来做前置。比如说
$FS,'{print $FS}' - 使用print的时候,可以格式化打印多个变量,可以是
'{print $1,$2}',或者是'{print $1 $2}',前者是传入两个参数,然后中间的空格是通过print的设置来生成的,而后者是传入一个参数,中间的空格就是传入的格式所决定的。(这本来是函数一节的内容,提前说了一下)
- 需要打印输出的时候,要像shell的语法一样,需要用$来做前置。比如说
各个选项
这个地方先不填,我们已经知道了的就是 -F & -v两个选项,还有其他的选项需要我们去了解,但是我选择以后了解,先把其他的学完,这个东西或许可以通过看awk的man文档,info文档来完善。
模式
模式换言之就是所谓的"条件" condition之谓也。模式有明文规定的一些模式如BEGIN、END,条件模式比如i<1,也有正则模式/192\.168\.1/总之,这些都是相当与if括号里面的条件,条件满足了,就会去执行其后跟着的方法
- BEGIN、END: BEGIN是awk开始读入文件之前需要执行的命令,如果没有传入任何文件,BEGIN里面的命令也会得到执行。END是所有的命令执行完毕之后会执行的命令,不多说了。
- 条件模式: | 关系运算符 |含义| | :-: | :-: | |~ |对应的正则表达式匹配为真 | |!~ |对应的正则表达式不为真 | |同C语言的符号|不用我多说了吧 =,!=,>+啥的|
- 空模式: 就是没有模式,空模式会匹配文件的每一行,所有的模式都会匹配上
- 正则匹配模式:
- 基本的语法:
awk '/^zsy/{printf $0}' /etc/passwd,这条命令会打印在/etc/passwd中的所有的以zsy开头的行。
- 注意的细节问题:
- 一定注意转义字符的问题,基本上如果非字母就要注意,但是我不知道多打了转义字符
\有没有影响。。。刚刚去试了一下,好像不行,所以还是记住所有的需要转义的符号吧。 - 如果需要使用正则表达式的高级用法的话,需要在选项里面加入
--posix或者是--re-interval来启用。
- 一定注意转义字符的问题,基本上如果非字母就要注意,但是我不知道多打了转义字符
- 高级的用法:
- 行范围模式:
awk '/正则1/,/正则2/{动作}', 表示当匹配到正则1的时候返回真,一直到匹配到正则2的行。
- 行范围模式:
- 基本的语法:
函数
这一块我记录的会比较松散,因为函数的确需要记忆,也需要使用。如果是不会经常用的函数的使用方法就没有必要记忆了,但是还是需要记录一下,知道有这么一个东西。
-
printf 函数:
- 用法:
printf "FORMAT" "TEXT1" "TEXT2" "..."其中,printf 后面带的都是参数,而最靠近printf的那个参数format规定了格式,后面的参数都是用来匹配格式的。 FORMAT:同C语言的printf()函数,有格式替换符还有转义字符。
- 用法:
-
其他的函数用到再总结,先给出朱双印老师的博客对应章节的地址。
高级用法
-
awk '{print $1}{pirnt $2}'表示一个模式中执行两个动作,相当于awk '{print $1; print $2}'。 -
awk '{if(NR==1){ print $0 }}' test表示对于所有的匹配空模式的(即所有的)行,如果满足这一行的行号为1的话就打印这一行。- 如果if后面有很多指令,print一句的大括号就不能够省略,但是现在只有print一条,所以就可以省略print这一句外面的大括号了。
- 除了if,还有if。。。else,if。。。else if。。。else的用法。
- awk还有循环以及遍历语句:
- for循环语句:
- for(初始化; bool表达式; 更新){代码语句}
- for(变量 in 数组){代码语句}
- while循环语句
- while(bool表达式){代码语句}
- do{代码语句}while(条件)
- for循环语句:
-
awk 的数组:
awk 'BEGIN{ huluwa[0]="大娃" print huluwa[5]}'- 上面那句话不会报错,而是会输出空字符,因为huluwa[0]句的确把"大娃"赋值给了"0",而数组被调用的时候如果没有创建的话,就会被自动创建为空字符。
- 所以说,如果我们需要检测哪个元素有没有被初始化,我们就需要语句
if(!(5 in huluwa))来检验。 - 注意的是,数组并不一定需要使用数字做标记,比如
huluwa["liwa"]="大娃"是可以的,这个特性让我想到了Python中的字典,接着往下看就知道我为什么这么说了。 - 遍历列表中的元素:
- 方法一:
for(i=0; i<10; i++){ print array[i] }这样的对应的是数字作为标记的数组方法,可以按照顺序来把数组打印出来。 - 方法二:
for(i in array){ print array[i] }读者会发现这里打印的顺序好像和我初始化的时候定义的顺序有点不太一样啊?的确如此,这里的数组是无序存储的,上面方法一可以按照顺序来索引是因为索引的递增不是依据数组的,而是依据我们在for后括号中定义的规则的。 如果读者把用数字来作为标记的数组来进行方法二遍历,那么便会得到乱序的表。所以说我看到这个的时候,我觉得它不应该叫做数组或者别的,它和Python的字典十分相像。
- 方法一:
-
打印奇偶行和三元运算
- 打印奇偶行:
awk 'i=!i' test2打印所有的奇数行awk '!(i=!i)' test 2打印所有的偶数行 原理是很多表达式都有值的概念,而赋值表达式a=b的值就是a也是b,(而awk中又是在调用的时候如果没有这个变量就会创建为空)(这句话存疑,读者可以自行验证,验证完之后告诉我一声:)),所以执行a=b的时候,先初始化a为空,然后初始化b为空(假设两者都没有被初始化),然后令a=b=空,所以表达式的值为空。 - 三元运算:
- 格式:
条件 ? 结果1 : 结果2 - 用法举例:
awk -F: '{ usertype=$3<500 ? "系统用户" : "普通用户"; print $1,usertype }' /etc/passwd
- 格式:
- 打印奇偶行:

浙公网安备 33010602011771号