AWK

Posted template

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AWK相关的知识,希望对你有一定的参考价值。

#AWK内建变量
变量                 意义                                  默认值
ARGC               命令行参数的个数                      -
ARGV               命令行参数数组                         -
FILENAME           当前输入文件名                         -
FNR                当前输入文件中的记录号                 -
FS                 控制着输入行的字段分割符               " " 
NF                 当前记录的字段个数                     -
NR                 目前为止已读的记录数量                 -
OFMT               数值的输出格式                        "%.6g"
OFS                输出字段分割符                        " "
ORS                输出的记录的分割符                    "
"
RLENGTH            被函数 match 匹配的字符串的长度          -
RS                 控制着输入行的记录分割符              "
"
RSTART             被函数 match 匹配的字符串的开始       
SUBSEP               下标分割符                            "34"


#字段变量
字段变量 (Field Variables). 当前输入行的字段从 $1, $2, 一直到 $NF; $0 表示整行



#AWK匹配方式

每次读取一个输入行, 对读取到的每一行, 按顺序检查每一个模 式. 对每一个与当前行匹配的模式, 对应的动作就会执行. 一个缺失的模式匹配每一个输入行, 因此每一个不带有模式的动作对每一个输入行都会执行. 只含有模式而没有动作的语句, 会打印每一个匹配模式的输入行 模式可以使用括号和逻辑运算符进行组合, 逻辑运算符包括 &&, ||, 和 !, 分别表示 AND,OR, 和NOT程序


#awk 中的循环:
echo "1000 0.2 3" | awk {i=1; while ( i <= $3 ) {printf("	%.2f
",$1 *(1 + $2) ^ i) ;i = i+1}}

echo "1000 0.2 3" | awk {for (i=1;i<=$3;i++) printf("	%.2f
",$1 *(1 + $2) ^ i)}


#倒序输出
awk { line[NR] = $0 } END {i = NR; while ( i > 0 ) { print line[i] ;i = i - 1 }} 

awk {line[NR] = $0} END{ for (i=NR;i>0;i--) print line[i] } emp.data 

打印包含Beth的行的数量
awk /Beth/ {lines = lines + 1} END {print lines} 

#打印最后一行最后一个字段
awk {filed = $NF} END {print filed}

#打印每一行的最后一个字段
awk {print $NF}

#打印具有最大值的第一个字段, 以及包含它的行 (假设 $1 总是 正的) 
awk $1 > max {max = $1;maxline = $0} END{print max,maxline}

#打印长度超过11的行
awk length($0) > 11

#交换每一行的第1与第2个字段,并打印该行
awk {temp = $1; $1 = $2; $2 = temp;print }

3打印删除了第二个字段后的行
awk {$2 = "";print}

#将每一行的字段按逆序打印
awk {for (i=NF;i>0;i--)printf("%s ",$i);printf("
")}

#打印每一行的所有字段值之和
awk {sum = 0; for (i = 1;i<= NF;i = i + 1) sum = sum + $i; print sum}

#将所有行的所有字段值累加起来
awk {for (i = 1;i<=NF;i++) sum = sum + $i} END{print sum}

#将每一行的每一个字段用它的绝对值替换
awk {for (i = 1;i <= NF;i++) if( $i< 0) $i = -$i; print }



AWK字符串匹配模式:

1. /regexpr/
当当前输入行包含一段能够被 regexpr 匹配的子字符串时, 该模式被匹配.

2. expression ~ /regexpr/   ($4 ~ /Asia/)
如果 expression 的字符串值包含一段能够被 regexpr 匹配的子字符时, 该模式被匹配.

3. expression !~ /regexpr/   
如果 expression 的字符串值不包含能够被 regexpr 匹配的子字符串, 该模式被匹配.
在 ~ 与 !~ 的语境中, 任意一个表达式都可以用来替换 /regexpr/ ($4 !~ /Asia//Asia/ 是 $0 ~ /Asia/的简写形式


#正则表达式元字符
 ^ $ . [ ] | ( ) * + ?


#awk中的转义序列
 退格
f 换页

 换行

 回车
t 制表符
ddd 八进制数 ddd, ddd 含有 13 个数字, 每个数字的值在 07 之间
c 其他的字面意义上的 c (举例来说, \ 表示反斜杠, " 表示双引号)


#awk复合模式
一个复合模式是一个组合了其他模式的表达式, 通过括号, 逻辑运算符 ||(OR), &&(AND), !(NOT) 来进行组合. 如果表达式的值为真, 那么复合模式就匹配当前输入行
$4 == "Asia" && $3 > 500

$4 == "Asia" || $4 == "Europe"


#范围模式
一个范围模式由两个被逗号分开的模式组成, 正如pat 1 , pat 2
awk /Canada/, /USA/ 匹配的行从包含 Canada 的行开始, 到包含 USA 的行结束.

#打印每一个输入文件的前五行,并在每一行的左边加上文件名
awk  FNR == 1, FNR == 5 { print FILENAME ": " $0 }

一个范围模式不能是其他模式的一部分

模式 例子 匹配
BEGIN BEGIN 输入被读取之前
END END 所有输入被读取完之后
expression $3 < 1003 个字段小于 100 的行
string-matching /Asia/ 含有 Asia 的行
compound $3 < 100 && $4 == "Asia"3 个字段小于100并且第4个字段含有 Asia 的行
range NR==10, NR==20 输入的第 10 行到第 20 行.


#AWK中的动作
动作中的语句可以包括:
expression, 包括常量, 变量, 赋值, 函数调用等等. 一个未初始化的变量的值是 "" (空字符串) 与 0.
print expression-list
printf(format, expression-list)
if (expression) statements
if (expression) statements else statements
while (expression) statements
for (expression; expression; expression) statements
for (expression in array) statements
do statements while (expression)
break
continue



[[email protected] scripts]# awk BEGIN {FS= OFS = "	"} $4 == "North America" {$4 = "NA"} ;$4 == "South America" {$4 = "SA" } ;{print} countries 
USSR    8649     275     Asia
Canada    3852     25         NA
China    3705     1032     Asia
USA        3615     237     NA
Brazil    3286     134     SA
India    1267     746     Asia
Mexico    762     78         NA
France    211     55         Europe
Japan    44        120     Asia
Germany    96        61        Europe
England    94        56        Europe


#条件表达式
expr 1 ? expr 2 : expr 3
先, expr 1 被求值. 如果值为真, 也就是值非零或非空, 那么整个条件表达式的值就会是 expr 2 的值; 否 则, 如果 expr 1 的值为假, 那么条件表达式的值就会是 expr 3 . expr 2expr 3 只有其中一个会被求值

#打印倒数
[[email protected] scripts]# echo "2 1" | awk {print ($1 != 0 ? 1/$1: "$1 is zero")} 
0.5
[[email protected] scripts]# echo "0 1" | awk {print ($1 != 0 ? 1/$1: "$1 is zero")} 
$1 is zero

#countries文件说明

[[email protected] scripts]# awk {print} countries 
USSR    8649     275     Asia
Canada    3852     25         North America
China    3705     1032     Asia
USA        3615     237     North America
Brazil    3286     134     South America
India    1267     746     Asia
Mexico    762     78         North America
France    211     55         Europe
Japan    44        120     Asia
Germany    96        61        Europe
England    94        56        Europe


awk $4 == "Asia" {pop += $3; n = n +1 } END {print "Total population of the", n, "Asian countries is", pop , "million" } countries 
Total population of the 4 Asian countries is 2173 million

第一个动作含有两个赋值语句, 第一个累积人口, 第二个计算国家的数量. 变量没有被显式地初始化, 但 程序仍然按照期望得那样运行, 这是因为每个变量都会默认初始化为空字符串 "" 或数值 0

[[email protected] scripts]# awk $3 > maxpop {maxpop = $3 ;country = $1} END {print "The country with largest population:", country,maxpop } countries

The country with largest population: China 1032

#

自增与自减 (Increment and Decrement Operators). 赋值语句:
    n = n + 1 通常写成 ++n 或 n++, 这里用到了一元自增运算符, 作用是给变量加 1. 前缀形式 ++n 在传递 n 的值之 前为 n 加 1; 后缀形式 n++ 在传递 n 的值之后, 为 n 加 1. 当 ++ 应用到赋值表达式时, 这会造成一些不 一样的地方. 如果 n 的初始值为 1, 赋值语句 i = ++n 为 n 加 1, 并将新值 2 赋给 i, 而 i = n++ 同样 为 n 加 1, 但将旧值 1 赋给 i. 如果仅仅是给 n 加 1, 那么 n++ 与 ++n 没什么区别. 前缀与后缀自减运 算符 -- 给变量减 1, 除此之外与 ++ 相同

[[email protected] scripts]# echo "" | awk {n=1;i=++n;print i} 
2
[[email protected] scripts]# echo "" | awk {n=1;i=n++;print i} 
1

#awk 内建算术函数
函数 返回值
atan2(y,x) y/x 的反正切值, 定义域在 ?π 到 π 之间
cos(x) x 的余弦值, x 以弧度为单位
exp(x) x 的指数函数, e x
int(x) x 的整数部分; 当 x 大于 0 时, 向 0 取整
log(x) x 的自然对数 (以 e 为底)
rand() 返回一个随机数 r, 0 ≤ r < 1
sin(x) x 的正弦值, x 以弧度为单位.
sqrt(x) x 的方根
srand(x) x 是 rand() 的新的随机数种子



#awk字符串拼接
因为字符串可以被拼接起来, 于是一个正则表达式可以由多个子部分构成. 下面这个程序将那些具
有有效浮点数的行打印出来:
BEGIN {
sign = "[+-]?"
decimal = "[0-9]+[.]?[0-9]*"
fraction = "[.][0-9]+"
exponent = "([eE]" sign "[0-9]+)?"
number = "^" sign "(" decimal "|" fraction ")" exponent "$"
}
$0 ~ number


内建字符串函数 

gsub(r,s) 将 $0 中所有出现的 r 替换为 s, 返回替换发生的次数.
gsub(r,s,t ) 将字符串 t 中所有出现的 r 替换为 s, 返回替换发生的次数
index(s,t) 返回字符串 t 在 s 中第一次出现的位置, 如果 t 没有出现
的话, 返回 0.
length(s) 返回 s 包含的字符个数
match(s,r) 测试 s 是否包含能被 r 匹配的子串, 返回子串的起始位置
或 0; 设置 RSTART 与 RLENGTH
split(s,a) 用 FS 将 s 分割到数组 a 中, 返回字段的个数
split(s,a,fs) 用 fs 分割 s 到数组 a 中, 返回字段的个数
sprintf(fmt,expr-list) 根据格式字符串 fmt 返回格式化后的 expr-list
sub(r,s) 将 $0 的最左最长的, 能被 r 匹配的子字符串替换为 s, 返
回替换发生的次数.
sub(r,s,t) 把 t 的最左最长的, 能被 r 匹配的子字符串替换为 s, 返回
替换发生的次数.
substr(s,p) 返回 s 中从位置 p 开始的后缀.
substr(s,p,n) 返回 s 中从位置 p 开始的, 长度为 n 的子字符串.

 

以上是关于AWK的主要内容,如果未能解决你的问题,请参考以下文章

awk

在awk代码中引用shell变量的方法

精通awk系列:awk读取行的细节

awk 脚本帮助 - 逻辑问题

linux awk命令的使用

sh 使用awk删除可执行代码的有效负载