Skip to content

Files

Latest commit

 Cannot retrieve latest commit at this time.

History

History
317 lines (231 loc) · 9.21 KB

A11.md

File metadata and controls

317 lines (231 loc) · 9.21 KB

Shell脚本编程

awk编程

awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。

awk命令说明:

awk '{ sum += $1 }; END{ print sum }' file_name
awk -F: '{ print $1 }' /etc/passwd

本文目录

awk模式和操作

awk脚本是由模式和操作组成的。进行awk编程时,先输入awk命名,然后输入 单引号的模式或动作,最后输入文件。若未指定文件,则使用键盘进行标准输入(stdin)。然后awk将已输入的数据用 空格或tab 隔开,分隔以$1开始的各字段变量进行识别。

模式

模式可以是以下任意一个:

  • /正则表达式/:使用通配符扩展集
  • 关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试
  • 模式匹配表达式:用运算符~(匹配)和!~(不匹配)
  • BEGIN语句块、pattern语句块、END语句块。

操作

awk中的操作是使用花括号{}的语句,以分号;分隔。模式在操作之前,操作可以创建为简单语句或高级语句。注意:若模式后面需要输入操作,必须在同一行输入第一个前花括号

pattern{action1; action2;}
或者
pattern{
  action1;
  action2;
}

awk输入

awk输入可以是文件,也可以使用键盘进行标准输入(stdin)。然后awk将输入的行数据用空格或Tab隔开,分割以$1开始的各字段变量进行识别。

从文件输入

awk 'pattern' filename
awk '{action}' filename
awk 'pattern {action}' filename

举例说明:

# vim awk_file
Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
awk '/Tom/' awk_file
awk '/Tom/ {print $3}' awk_file
awk '{print $1,$3}' awk_file

从指令输入

使用管道操作符|,可以从指令输入。

command | awk 'pattern'
command | awk '{action}'
command | awk 'pattern {action}'

awk工作原理

awk 'BEGIN{ commands } pattern{ commands } END{ commands }'

1)执行BEGIN{ commands }语句块中的语句;

2)从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕;

3)当读至输入流末尾时,执行END{ commands }语句块。

  • BEGIN语句块 在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。

  • END语句块 在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

  • pattern语句块 中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

awk输出

awk中的动作部分(action),可使用print函数以{print}格式显示输出。print函数中允许使用转义字符:

print函数的转义字符

转义字符 含义
\b 退格
\f 换页符
\n newline下一行
\r 回车
\t Tab
\047 八进制47
\c c代表字符

显示数字时,往往需要控制数字格式,可以使用OFMT(OutputForMaT,输出格式)变量。其默认格式是%.6g。

awk 'BEGIN{OFMT="%.2f"; print 1.23456, 15E-3}'

printf函数与C语言的printf语句一样,通过标准输出返回已格式化字符串。与print函数不同,printf函数不提供newline。若需要newline,使用"\n"转义字符。

printf格式指示符

格式指示符 说明
%c 显示一个ASCII字符
%d 显示一个十进制数
%e 显示e符号的数字
%f 显示float实数型数字
%o 显示八进制数
%s 显示字符串
%x 显示16进制数
另外,配合"-"的使用,可以实现左侧开始显示,否则默认从右侧显示。
# 显示为|LINUX     |
$ echo "LINUX" | awk '{printf "|%-15s|", $1}'

awk -f选项

若文件已经生成awk动作和命令,则使用-f选项。其语法如下:

awk -f [awk命令文件] [awk命令适用文件]

举例说明:

# awk_cmd
# {print "Hello," $1 "!"}
$ awk -f awk_cmd awk_file

awk记录和字段

记录

在awk的输入数据中,各行成为“记录”,默认以newline分隔,称为 记录分隔符,保存在内置变量ORS和RS中。

  • $0变量:awk中所有记录都被浏览为$0。
  • NR变量:每个记录号保存在awk内置变量NR。记录保存后,NR值就加1。
awk '{print NR, $0}' awk_file

字段

每个记录默认由词组成,所谓的词是由 空格或Tab 分隔的字段组成,每个词成为一个字段。awk中内置变量NF保存字段数,每个NF值一般可拥有100各字段。awk内置变量FS保存输入字段分隔符的值,默认值为空格和Tab,在BEGIN语句或命令行可以更改FS值,在命令行中使用-F选项来更改此值。

awk '{print $0, NF}' awk_file
awk -F: '/Tom/ {print $1, $3}' awk_file
awk -F'[ :\t]' '/Tom/ {print $1, $3}' awk_file

awk和正则表达式

awk的正则表达式是使用斜杠/且由字符串组成的模式,并且支持正则表达式的元字符。

awk支持的元字符

awk元字符 含义
^ 匹配字符串的开头
$ 匹配字符串的末尾
. 匹配1个字符
* 匹配0及0个以上字符
+ 匹配1及多个字符
- 匹配0或1个字符
[ABC] A、B、C字符集之中只匹配1个字符
[^ABC] A、B、C字符集之中无匹配字符
[A-Z] A~Z范围内存在匹配字符
A|B 匹配A或B字符
(AB)+ 匹配多个AB字符集
* 匹配星号*字符
& 在检索字符串中用检索出的字符串替代

awk重定向

输出重定向

将awk的结果重定向至文件时,可使用shell重定向运算符>,但是,文件名必须使用双引号。

$ awk -F: '$4 >= 200 { print $1, $2 > "output_file" }' file_name

输入重定向

awk中利用gitline函数实现输入重定向。getline函数检索到记录则返回1,检索至文件末尾,则返回0,若发生错误则返回-1。

awk 'BEGIN{"date" | getline d; print d}'

awk管道

在awk程序中打开管道时,打开其他管道前需要先关闭已打开的管道。管道操作符右侧命令必须使用双引号

awk '{print $1 | "sort -r"}' awk_file

脚本文件中的awk

在脚本文件中可以使用多个awk模式和动作。脚本是包含awk注释和语句的文件,必须以分号(;)分隔同一行中的语句和动作,已分隔的行中无需使用分号。若模式后面输入动作,则必须在同一行输入前花括号({)和模式。

比较表达式

比较表达式检索的行只有在状态显示为真时,才能执行动作,表达式使用关系运算符比较数字和字符串。

比较运算符

比较字符 含义 示例
< 小于 x<y
<= 小于等于 x<=y
== 等于 x==y
!= 不等于 x!=y
>= 大于等于 x>=y
> 大于 x>y
~ 匹配正则表达式 x~/y/
!~ 与正则表达式不匹配 x!~/y/
$ awk '$2 == 20 { print $1 }' file_name

条件表达式

条件表达式(A?B:C)检查表达式时,使用问好和冒号。

$ awk '{ max=($1 > $2) ? $1 : $2; print max }' file_name

算数运算符与逻辑运算符

awk中支持的算数运算符包括:+,-,*,/,%,^;逻辑运算符包括:&&,||,!

awk变量

awk不会另外定义用户自定义变量,但可以在表达式中根据变量上下文预测数据类型,将字符串变量和数字型变量分别初始化为NULL和0。

awk中的赋值运算符包括:=, +=, -=, *=, /=, %=, ^=

条件语句

if条件语句

格式为:

if(条件表达式) {
  语句1;语句2;
}

if/else语句

格式为:

if(条件表达式) {
  语句1;语句2;
}
else {
  语句1;语句2;
}
$ awk '{if($1 > 100){ print $1 "大于100" } else { print $1 "小于100" }}' file_name

当遇到比较复杂的条件语句应该考虑使用脚本文件的方式进行awk编程。

# awk_file
{
if ($2 > 89 && $2 < 101)
  print $1, "的学分是:Grade A"
else if($2 > 79)
  print $1, "的学分是:Grade B"
else if($2 > 69)
  print $1, "的学分是:Grade C"
else if($2 > 59)
  print $1, "的学分是:Grade D"
else
  print $1, "的学分是:Grade F"
}

数组