Linux运维相关(七)
学习Linux运维过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
—— AWK 介绍 ——
-
awk 有 3 个不同版本: awk、nawk 和 gawk,未作特别说明,一般指 gawk。
-
awk 语言的最基本功能是在文件或字符串中基于指定规则来分解抽取信息,也可以基于指定的规则来输出数据。完整的 awk 脚本通常用来格式化文本文件中的信息。
-
三种方式调用 awk
- awk [opion] ‘awk_script’ input_file1 [input_file2 …] awk 的常用选项 option 有;
- ① -F fs : 使用 fs 作为输入记录的字段分隔符,如果省略该选项,wak 使用环境变量 IFS 的值
- ② -f filename : 从文件 filename 中读取 awk_script
- ③ -v var=value : 为 awk_script 设置变量
- 将 awk_script 放入脚本文件并以
#!/bin/awk -f
作为首行,给予该脚本可执行权限,然后在 shell 下通过键入该脚本的脚本名调用之。 - 将所有的 awk_script 插入一个单独脚本文件,然后调用: awk -f wak 脚本文件 input_file(s)
- awk [opion] ‘awk_script’ input_file1 [input_file2 …] awk 的常用选项 option 有;
-
awk 的运行过程
-
(1) awk_script 的组成:
- ① awk_script 可以由一条或多条 awk_cmd 组成,两条 awk_cmd 之间一般以 NEWLINE 分隔
- ② awk_cmd 由两部分组成: awk_pattern { actions }
- ③ awk_script 可以被分成多行书写,必须确保整个 awk_script 被单引号括起来。
-
(2) awk 命令的一般形式:
-
(3) awk 的运行过程:
- ① 如果 BEGIN 区块存在,awk 执行它指定的 actions。
- ② awk 从输入文件中读取一行,称为一条输入记录。(如果输入文件省略,将从标准输入读取)
- ③ awk 将读入的记录分割成字段,将第 1 个字段放入变量$1 中,第 2 个字段放入$2,以此类推。$0 表示整条 记录。字段分隔符使用 shell 环境变量 IFS 或由参数指定。
- ④ 把当前输入记录依次与每一个 awk_cmd 中 awk_pattern 比较,看是否匹配,如果相匹配,就执行对应的 actions。如果不匹配,就跳过对应的 actions,直到比较完所有的 awk_cmd。
- ⑤ 当一条输入记录比较了所有的 awk_cmd 后,awk 读取输入的下一行,继续重复步骤③和④,这个过程一直 持续,直到 awk 读取到文件尾。
- ⑥ 当 awk 读完所有的输入行后,如果存在 END,就执行相应的 actions。
-
(4) iput_file 可以是多于一个文件的文件列表,awk 将按顺序处理列表中的每个文件。
-
(5) 一条 awk_cmd 的 awk_pattern 可以省略,省略时不对输入记录进行匹配比较就执行相应的 actions。一条 awk_cmd 的 actions 也可以省略,省略时默认的动作为打印当前输入记录(print $0) 。一条 awk_cmd 中的 awk_pattern 和 actions 不能同时省略。
-
(6) BEGIN 区块和 END 区块别位于 awk_script 的开头和结尾。awk_script 中只有 END 区块或者只有 BEGIN 区块 是被允许的。如果 awk_script 中只有 BEGIN { actions } ,awk 不会读取 input_file。
-
(7) awk 把输入文件的数据读入内存,然后操作内存中的输入数据副本,awk 不会修改输入文件的内容。
-
(8) awk 的总是输出到标准输出,如果想让 awk 输出到文件,可以使用重定向。
-
-
awk_pattern awk_pattern 模式部分决定 actions 动作部分何时触发及触发 actions。awk_pattern 可以是以下几种类型:
- (1) 正则表达式用作 awk_pattern: /regexp/
- ① awk 中正则表达式匹配操作中经常用到的字符:
\ ^ $ . [] | () * // 通用的 regexp 元字符
+
: 匹配其前的单个字符一次以上,是 awk 自有的元字符,不适用于 grep 或 sed 等?
: 匹配其前的单个字符 1 次或 0 次,是 awk 自有的元字符,不适用于 grep 或 sed 等
- ② 举例:
awk '/ *\$0\.[0-9][0-9].*/' input_file
- ① awk 中正则表达式匹配操作中经常用到的字符:
- (2) 布尔表达式用作 awk_pattern,表达式成立时,触发相应的 actions 执行。
- ① 表达式中可以使用变量(如字段变量$1,$2 等)和/regexp/
- ② 布尔表达式中的操作符:
- 关系操作符:
< > <= >= == !=
- 匹配操作符:
value ~ /regexp/
如果 value 匹配/regexp/,则返回真
value !~ /regexp/
如果 value 不匹配/regexp/,则返回真
举例:
awk '$2 > 10 {print "ok"}' input_file
awk '$3 ~ /^d/ {print "ok"}' input_file
- 关系操作符:
- ③ &&(与) 和 ||(或) 可以连接两个/regexp/或者布尔表达式,构成混合表达式。!(非) 可以用于布尔表达 式或者/regexp/之前。
举例:
awk '($1 < 10 ) && ($2 > 10) {print "ok"}' input_file
awk '/^d/ || /x$/ {print "ok"}' input_file
- ④ 其它表达式用作 awk_script,如赋值表达式等
awk '(tot+=$6); END{print "total points :" tot }' input_file // 分号不能省略
awk 'tot+=$6 {print $0} END{print "total points :" tot }' input_file // 与上面等效
- (1) 正则表达式用作 awk_pattern: /regexp/
-
actions actions 就是对 awk 读取的记录数据进行的操作。actions 由一条或多条语句或者命令组成,语句、命令之间 用分号(;)分隔。actions 中还可以使用流程控制结构的语句。
-
(1) awk 的命令:
- ① print 参数列表 : print 可以打印字符串(加双引号)、变量和表达式,是 awk 最基本的命令。参数列表 要用逗号(,)分隔,如果参数间用空格分隔,打印出时参数值之间不会有空格。
- ② printf ([格式控制符],参数) : 格式化打印命令(函数),语法与 C 语言的 printf 函数类似。
- ③ next : 强迫 awk 立刻停止处理当前的记录,而开始读取和处理下一条记录。
- ④ nextfile : 强迫 awk 立刻停止处理当前的输入文件而处理输入文件列表中的下一个文件
- ⑤ exit : 使 awk 停止执行而跳出。如果有 END 存在,awk 会去执行 END 的 actions。
-
(2) awk 的语句: awk 的语句主要是赋值语句,用来给变量赋值。
- ① 把直接值或一个变量值赋值给变量。如果直接值是字符串要加双引号。
举例:awk 'BEGIN {x=1 ; y=3 ; x=y ; print "x=" x " ; y=" y }'
- ② 把一个表达式的值赋值给变量。表达式一般是数值表达式,也可以是其它表达式。
数值表达式:num1 operator num2
operator 可以是:+(加) -(减) *(乘) /(除) %(取模) ^(求幂)
当 num1 或者 num2 是字符串而是不是数字时,无论是否加有双引号,awk 都视其值为 0 条件选择表达式: A?B:C (A 为布尔表达式,B 和 C 可以是表达式或者直接值) 当布尔表达式 A 的值为真时,整个表达式的值为 B,A 的值为假时,整个表达式的值为 C
举例:awk 'BEGIN {x=3 ; x+=2 ; y=x+2 ; print "x=" x " ; y=" y }' awk 'BEGIN {x=3 ; y=x>4?"ok":4 ; print "x=" x " ; y=" y }'
- ① 把直接值或一个变量值赋值给变量。如果直接值是字符串要加双引号。
-
③ 为了方便书写,awk 也支持 C 语言语法的赋值操作符:
+= -= *= /= %= ^= ++ --
-
(3) 流程控制结构 (基本上是使用 C 语言的语法) 其中 condition 一般为布尔表达式,body 和 else-body 是 awk 语句块。
- ① if (condition) {then-body} [else {else-body}]
- ② while (condition) {body}
- ③ do {body} while (condition)
- ④ for (initialization; condition; increment) {body} 与 C 语言的 for 结构的语法相同。
- ⑤ break : 跳出包含它的 for、while、do-while 循环 ⑥ continue : 跳过 for、while、do-while 循环的 body 的剩余部分,而立刻进行下一次循环的执行。
-
-
awk 的变量 在 awk_script 中的表达式中要经常使用变量。不要给变量加双引号,那样做,awk 将视之为字符串。
awk 的变 量基本可以分为两类:-
(1) awk 内部变量: awk 的内部变量用于存储 awk 运行时的各种参数,这些内部变量又可以分为:
- ① 自动内部变量: 这些变量的值会随着 awk 程序的运行而动态的变化,在 awk_script 中改变这些变量的值是 没有意义的(即不应该被赋值)。常见的有:
- NF : 当前输入字段的字段数
- NR : 对当前输入文件而言,已经被 awk 读取过的记录(行)的数目。
- FNR : 已经被 awk 读取过的记录(行)的总数目。当输入文件只有一个时,FNR 和 NR 是一致的。
- FILENAME : 当前输入文件的文件名。
- ARGC : 命令行参数个数。(不包括选项和 awk_script,实际就是输入文件的数目加 1)
- ARGIND : 当前被处理的文件在数组 ARGV 内的索引( 实际上 ARGV[1]就是第一个输入文件 )
举例:awk '{print NR,NF,$0} END {print FILENAME}' input_file
- ② 字段变量($0 $1 $2 $3 …): 当 awk 把当前输入记录分段时,会对这些字段变量赋值。和内部变量类似, 在 awk 运行过程中字段变量的值是动态变化的。不同的是,修改这些字段变量的值是有意义的,被修改的字段 值可以反映到 awk 的输出中。 可以创建新的输出字段,比如,当前输入记录被分割为 8 个字段,这时可以通过对变量 $9 (或$9 之后的 字段变量)赋值而增加输出字段,NR 的值也将随之变化。 字段变量支持变量名替换。
举例:
pwd |awk -F/ '{print $NF}' // print $NF 打印输入记录的最后一个字段
awk '{x=2;print $x}' input_file // 打印输入记录的第 2 个字段
- ③ 其它内部变量: 可以修改这些变量。常见的有:
- FS : 输入记录的字段分隔符(默认是空格和制表符)
- OFS : 输出记录的字段分隔符(默认是空格)
- OFMT : 数字的输出格式(默认是 %.6g)
- RS : 输入记录间的分隔符(默认是 NEWLINE)
- ORS : 输出记录间的分隔符(默认是 NEWLINE)
- ARGV : 命令行参数数组
- ENVIRON : 存储系统当前环境变量值的数组,它的每个成员的索引就是一个环境变量名,而对应的值 就是相应环境变量的值。可以通过给 ENVIRON 数组的成员赋值而改变环境变量的值,但是新值只在 awk_script 内有效。eg: ENVIRON[“HISTSIZE”]=500
举例:cat /etc/passwd | awk 'BEGIN { FS=":" } {print "User name: "$1,"UID: "$4}'
- ① 自动内部变量: 这些变量的值会随着 awk 程序的运行而动态的变化,在 awk_script 中改变这些变量的值是 没有意义的(即不应该被赋值)。常见的有:
-
(2) 自定义变量
- 定义变量: varname=value (自定义变量不需先声明后使用,赋值语句同时完成变量定义和初始化)
- 在表达式中出现不带双引号的字符串都被视为变量,如果之前未被赋值,默认值为 0 或空字符串。
- 向命令行 awk 程序传递变量的值:
- ① Usage:
awk 'awk_script' awkvar1=value1 awkvar2=value2 .... input_file
eg:awk '{if ($5 < ARG) print $0 }' ARG=100 input_file
- ② awkvar 可以是 awk 内置变量或自定义变量。
- ③ awkvar 的值将在 awk 开始对输入文件的第一条记录应用 awk_script 前传入。如果在 awk_script 中已经对 某个变量赋值,那么在命令行上传人到该变量的值就会无效(实际上是 awk_script 中的赋值语句覆盖了从命令 行上传入的值)。
- ④ 在 awk 脚本程序中不能直接使用 shell 的变量。通过使用下面的语法可达到这样的效果。
awk 'awk_script' awkvar1=shellvar1 awkvar2=shellvar2 .... input_file
eg:awk '{if (v1 == "root") {print "User name is root!"}}' v1=$USER input_file
- ⑤ 可以向 awk 脚本传递变量的值,与上面的类似。
awk_script_file awkvar1=value1 awkvar2=value2 ... input_file
- ① Usage:
-
-
awk 的内置函数 可以在 awk_script 的任何地方使用 awk 函数。和 awk 变量一样,awk 函数可以分为内置函数和自定义函数。
- (1) 常见 awk 内置数值函数
- int(x) : 求出 x 的整数部份,朝向 0 的方向做舍去。eg: int(3.9)是 3,int(-3.9) 是-3。
- sqrt(x) : 求出 x 正的平方根值。eg: sqrt(4)=2
- exp(x) : 求出 x 的次方。eg: exp(2) 即是求 e*e 。
- log(x) : 求出 x 的自然对数。
- sin(x) : 求出 x 的 sine 值,x 是弪度量。
- cos(x) : 求出 x 的 cosine 值,x 是弪度量。
- atan2(y,x) : 求 y/x 的 arctangent 值,所求出的值其单位是弪度量。
- rand() : 得到一个随机数(平均分布在 0 和 1 之间)。每次执行 gawk,rand 从相同的 seed 生成值。
- srand(x) : 设定产生随机数的 seed 为 x。如果在第二次运行 awk 程序时你设定相同的 seed 值,你将再 度得到相同序列的随机数。如果省略引数 x,例如 srand(),则当前日期时间会被当成 seed。这个方法可使得 随机数值是真正不可预测的。
- srand() : 其值是当次 awk_script 运行过程中前次 srand(x)的设定的 seed 值 x,。
- (2) 常见 awk 内置字符串函数
- index(in, find) : 返回字符串 in 中字符串 find 第一次出现的位置(索引从 1 开始),如果在字串 in 中找 不到字符串 find,则返回值为 0。
eg:print index("peanut","an")
会印出 3。 - length(s) : 求出字符串 s 的字符个数。
eg:length("abcde")
是 5。 - match(s,r) : 返回模式字符串 r 在字符串 s 的第一次出现的位置,如果 s 不包含 r,则返回值 0。
- sprintf(fmt,exp1,…) : 和 printf 类似印出,是 sprintf 不是打印而是返回经 fmt 格式化后的 exp。
eg:sprintf("pi = %.2f (approx.)",22/7)
传回的字串为"pi = 3.14 (approx.)" - sub(p, r,t) : 在字符串 t 中寻找符合模式字符串 p 的最靠前最长的位置,并以字符串 r 代替最前的 p。
eg:str = "water, water"sub(/at/, "ith",str)
结果字符串 str 会变成"wither, water" - gsub(p, r, t) : gsub 与 sub 类似。不过时在字符串 t 中以字符串 r 代替所有的 p。 eg:
str="water, water" ; gsub(/at/, "ith",str)
结果字符串 str 会变成"wither,wither" - substr(str, st, len) : 传回 str 的子字符串,其长度为 len 字符,从 str 的第 st 个位置开始。如 果 len 没有出现,则传回的子字符串是从第 st 个位置开始至结束。
eg:substr("washington",5,3)
传回值为"ing" - substr(“washington”,5) 传回值为"ington" split(s,a,fs) : 在分隔符 fs 为分隔符将字符串 s 分隔成一个 awk 数组 a,并返回 a 的下标数。
eg:awk 'BEGIN{print split("123#456#789",myarray,"#")}'
将打印 3 。 - tolower(str) : 将字符串 str 的大写字母改为小写字母。 eg: tolower(“MiXeD cAsE 123”) 传回值为"mixed case 123"
- toupper(str) : 将字符串 string 的小写字母改为大写字母。
- eg:
toupper("MiXeD cAsE 123")
传回值为"MIXED CASE 123" 3) 常见 awk 内置系统函数 - close(filename) : 将输入或输出的文件 filename 关闭。
- system(command) : 此函数允许调用操作系统的指令,执行完毕後将回到 awk 程序。
eg:awk 'BEGIN {system("ls")}'
- index(in, find) : 返回字符串 in 中字符串 find 第一次出现的位置(索引从 1 开始),如果在字串 in 中找 不到字符串 find,则返回值为 0。
- (1) 常见 awk 内置数值函数
-
复杂的 awk 常常可以使用自己定义的函数来简化。调用自定义的函数与调用内置函数的方法一样。
-
- 自定义函数定义的格式: 自定义函数可以在 awk 程序的任何地方定义。
function fun_name (parameter_list) { // parameter_list 是以逗号分隔的参数列表 body-of-function // 函数体,是 awk 语句块 }
-
- 举例:
awk '{ print "sum =",SquareSum($1,$2) }
function SquareSum(x,y) { sum=x*x+y*y ; return sum } ' grade.txt
- 举例:
-
awk 的数组 数组使用前,不必预先定义,也不必指定数组元素个数。
- (1) 访问数组的元素。经常使用循环来访问数组元素,下面是一种循环类型的基本结构:
for (element in array_name ) print array_name[element]
- (2) 举例:
awk 'BEGIN{print split("123#456#789",mya,"#") ; for (i in mya) { print mya[i] }} '
- (1) 访问数组的元素。经常使用循环来访问数组元素,下面是一种循环类型的基本结构: