linux+中awk用法,Linux Awk用法总结

内置变量

Awk在内部维护了许多内置变量,或者称为系统变量,例如之前提到的FS、RS等等。常见的内置变量如下表所示

变量名

描述

ARGC

命令行参数的各个,即ARGV数组的长度

ARGV

存放命令行参数

CONVFMT

定义awk内部数值转换成字符串的格式,默认值为"%.6g"

OFMT

定义输出时数值转换成字符串的格式,默认值为"%.6g"

ENVIRON

存放系统环境变量的关联数组

FILENAME

当前被处理的文件名

NR

记录的总个数

FNR

当前文件中的记录的总个数

FS

字段分隔符,默认为空白

NF

每个记录中字段的个数

RS

记录的分隔符,默认为回车

OFS

输出时字段的分隔符,默认为空白

ORS

输出时记录的分隔符,默认为回车

RLENGTH

被match函数匹配的子串长度

RSTART

被match函数匹配的子串位于目标字符串的起始下标

下面主要介绍几个比较难理解的内置变量:

1.ARGV与ARGC

ARGV与ARGC的意思比较好理解,就像C语言main(int argc, char **argv)。ARGV数组的下标从0开始到ARGC-1,它存放的是命令行参数,并且排除命令行选项(例如-v/-f)以及program部分。因此事实上ARGV只是存储argument的部分,即文件名(file)以及命令行变量赋值两部分的内容。

通过下面的例子可以大概了解ARGC与ARGV的用法:

[kodango@devops awk_temp]$ awk 'BEGIN {> for (i = 0; i < ARGC; i++)> print ARGV[i]> }' inventory-shipped BBS-listawkinventory-shippedBBS-list

ARGV的用法不仅限于此,它是可以修改的,可以更改数组元素的值,可以增加数组元素或者删除数组元素。

a. 更改ARGV元素的值

假设我们有a, b两个文件,它们各有一行内容:file a和file b。现在利用ARGV,我们可以做到偷梁换柱:

[kodango@devops awk_temp]$ awk 'BEGIN{ARGV[1]="b"} {print}' afile b

这里要注意ARGV[1]="b"的引号不能缺少,否则ARGV[1]=b会将变量b的值赋值给ARGV[1]。

当awk处理完一个文件之后,它会从ARGV的下一个元素获取参数,如果是一个文件则继续处理,如果是一个变量赋值则执行赋值操作:

[kodango@devops awk_temp]$ awk 'BEGIN{ARGV[1]="var=1"} {print var}' a b1

为什么这里只打印一次变量值呢?可以回头再看看上一篇中介绍变量赋值的内容。

而当下一个元素为空时,则跳过不处理,这样可以避开处理某个文件:

[kodango@devops awk_temp]$ awk 'BEGIN{ARGV[1]=""} {print}' a bfile b

上面的例子中a这个文件就被跳过了。

而当下一个元素的值为"-"时,表明从标准输入读取内容:

[kodango@devops awk_temp]$ awk 'BEGIN{ARGV[1]="-"} {print}' a baa # --> 这里按下CTRL+D停止输入file b

b. 删除ARGV元素

删除ARGV元素和将元素的值赋值为空的效果是一样的,它们都会跳转对某个参数的处理:

[kodango@devops awk_temp]$ awk 'BEGIN{delete ARGV[1]} {print}' a bfile b

删除数组元素可以用delete语句。

c. 增加ARGV元素

我第一次看到ARGV变量的时候就在想,能不能利用ARGV变量避免提供命令行参数,就像这样:

awk 'BEGIN{ARGV[1]="a";} {print}'

但是事实上这样不行,awk会依然从标准输入中获取内容。下面的方法倒是可以,首先增加ARGC的值,再增加ARGV元素,我到现在也没搞懂这两者的区别:

[kodango@devops awk_temp]$ awk 'BEGIN{ARGC+=1;ARGV[1]="a"} {print}'file a

2.CONVFMT与OFMT

Awk中允许数值到字符串相互转换,其中内置变量CONVFMT定义了awk内部数值到字符串转换的格式,它的默认值为"%.6g":

[kodango@devops awk_temp]$ awk 'BEGIN { printf "CONVFMT=%s, num=%f, str=%s\n", CONVFMT, 12.11, 12.11}' CONVFMT=%.6g, num=12.110000, str=12.11

通过更改CONVFMT,我们可以定义自己的转换格式:

[kodango@devops awk_temp]$ awk 'BEGIN { CONVFMT="%d"; printf "CONVFMT=%s, num=%f, str=%s\n", CONVFMT, 12.11, 12.11 }' CONVFMT=%d, num=12.110000, str=12

与此对应地还有一个内置变量OFMT,它与CONVFMT的作用是类似的,只不过是影响输出的时候数字转换成字符串的格式:

[kodango@devops awk_temp]$ awk 'BEGIN { OFMT="%d";print 12.11 }' 12

3.ENVIRON

ENVIRON是一个存放系统环境变量的关联数组,它的下标是环境变量名称,值是相应环境变量的值。例如:

[kodango@devops awk_temp]$ awk 'BEGIN { print ENVIRON["USER"] }' kodango

利用环境变量也可以将值传递给awk:

[kodango@devops awk_temp]$ U=hello awk 'BEGIN { print ENVIRON["U"] }' hello

可以利用for..in循环遍历ENVIRON数组:

[kodango@devops awk_temp]$ awk 'BEGIN { for (env in ENVIRON) printf "%s=%s\n", env, ENVIRON[env]; }'

4.RLENGTH与RSTART

RLENGTH与RSTART都是与match函数相关的,前者表示匹配的子串长度,后者表示匹配的子串位于目标字符串的起始下标。例如:

[kodango@devops ~]$ awk 'BEGIN {match("hello,world", /llo/); print RSTART,RLENGTH}'3 3

关于match函数,我们会在以后介绍。

运算符

表达式中必然少不了运算符,awk支持的运算符可以参见man手册中的“Expressions in awk”一小节内容:

[kodango@devops awk_temp]$ man awk | grep "^ *Table: Expressions in" -A 42 | sed 's/^ *//' Table: Expressions in Decreasing Precedence in awkSyntax Name Type of Result Associativity( expr ) Grouping Type of expr N/A$expr Field reference String N/A++ lvalue Pre-increment Numeric N/A-- lvalue Pre-decrement Numeric N/Alvalue ++ Post-increment Numeric N/Alvalue -- Post-decrement Numeric N/Aexpr ^ expr Exponentiation Numeric Right! expr Logical not Numeric N/A+ expr Unary plus Numeric N/A- expr Unary minus Numeric N/Aexpr * expr Multiplication Numeric Left...以下省略...

语句(Statement)

到目前为止,用得比较多的语句就是print,其它的还有printf、delete、break、continue、exit、next等等。这些语句与函数不同的是,它们不会使用带括号的参数,并且没有返回值。不过也有意外,比如printf就可以像函数一样的调用:

[kodango@devops awk_temp]$ echo 1 | awk '{printf("%s\n", "abc")}'abc

break和continue语句,大家应该比较了解,分别用于跳出循环和跳到下一个循环。

delete用于删除数组中的某个元素,这个我们在上面介绍ARGV的时候也使用过。

exit的用法顾名思义,就是退出awk的处理,然后会执行END部分的内容:

[kodango@devops awk_temp]$ echo $'line1\nline2' | awk '{print;exit} END {print "exit.."}' line1exit..

next语句类似sed的n命令,它会读取下一条记录,并重新回到脚本的最开始处执行:

[kodango@devops awk_temp]$ echo $'line1\nline2' | awk '{> print "Before next.."> print $0 > next> print "After next.."> }'Before next..line1Before next..line2

从上面可以看出next后面的print语句不会执行。

print与printf语句是使用最多的,它们将内容输出到标准输出。注意在print语句中,输出的变量之间带不带逗号是有区别的:

[kodango@devops awk_temp]$ echo "1 2" | awk '{print $1, $2}'1 2[kodango@devops awk_temp]$ echo "1 2" | awk '{print $1 $2}'12

print输出时,字段之间的分隔符可以由OFS重新定义:

[kodango@devops awk_temp]$ echo "1 2" | awk '{OFS=";";print $1,$2}'1;2

除此之外,print的输出还可以重定向到某个文件中或者某个命令:

print items > output-fileprint items >> output-fileprint items | command

假设有这一样一个文件,第一列是语句名称,第二列是对应的说明:

[kodango@devops awk_temp]$ cat column.txt statement|descriptiondelete|delete item from an arrayexit|exit from the awk processnext|read next input record and process

现在我们要将两列的内容分别输出到statement.txt和description.txt两个文件中:

[kodango@devops awk_temp]$ awk -F'|' '{> print $1 > "statement.txt";> print $2 > "description.txt"> }' column.txt [kodango@devops awk_temp]$ cat statement.txt statementdeleteexitnext[kodango@devops awk_temp]$ cat description.txt descriptiondelete item from an arrayexit from the awk processread next input record and process

下面是一个重定向到命令的例子,假设我们要对下面的文件进行排序:

[kodango@devops awk_temp]$ cat num.list 13295

可以通过将print的内容重定向到"sort -n"命令:

[kodango@devops awk_temp]$ awk '{print | "sort -n"}' num.list 12359

printf命令的用法与print类似,也可以重定向到文件或者输出,只不过printf比print多了格式化字符串的功能。printf的语法也大多数语言包括bash的printf命令类似,这里就不多介绍了。

数学函数

awk中支持以下数学函数:

atan2(y,x):反正切函数;

cos(x):余弦函数;

sin(x):正弦函数;

exp(x):以自然对数e为底指数函数;

log(x):计算以e 为底的对数值;

sqrt(x):绝对值函数;

int(x):将数值转换成整数;

rand():返回0到1的一个随机数值,不包含1;

srand([expr]):设置随机种子,一般与rand函数配合使用,如果参数为空,默认使用当前时间为种子;

例如,我们使用rand()函数生成一个随机数值:

[kodango@devops awk_temp]$ awk 'BEGIN {print rand(),rand();}'0.237788 0.291066[kodango@devops awk_temp]$ awk 'BEGIN {print rand(),rand();}'0.237788 0.291066

但是你会发现,每次awk执行都会生成同样的随机数,但是在一次执行过程中产生的随机数又是不同的。因为每次awk执行都使用了同样的种子,所以我们可以用srand()函数来设置种子:

[kodango@devops awk_temp]$ awk 'BEGIN {srand();print rand(),rand();}'0.171625 0.00692412[kodango@devops awk_temp]$ awk 'BEGIN {srand();print rand(),rand();}'0.43269 0.782984

这样每次生成的随机数就不一样了。

利用rand()函数我们也可以生成1到n的整数:

[kodango@devops awk_temp]$ awk '> function randint(n) { return int(n*rand()); }> BEGIN { srand(); print randint(10);> }'3

字符串函数

awk中包含大多数常见的字符串操作函数。

1.sub(ere, repl[, in])

描述:简单地说,就是将in中匹配ere的部分替换成repl,返回值是替换的次数。如果in参数省略,默认使用$0。替换的动作会直接修改变量的值。

下面是一个简单的替换的例子:

[kodango@devops ~]$ echo "hello, world" | awk '{print sub(/ello/, "i"); print}'1hi, world

在repl参数中&是一个元字符,它表示匹配的内容,例如:

[kodango@devops ~]$ awk 'BEGIN {var="kodango"; sub(/kodango/, "hello, &", var); print var}'hello, kodango

2.gsub(ere, repl[, in])

描述:同sub()函数功能类似,只不过是gsub()是全局替换,即替换所有匹配的内容。

3.index(s, t)

描述:返回字符串t在s中出现的位置,注意这里位置是从1开始计算的,如果没有找到则返回0。

例如:

[kodango@devops ~]$ awk 'BEGIN {print index("kodango", "o")}'2[kodango@devops ~]$ awk 'BEGIN {print index("kodango", "w")}'0

4.length[([s])]

描述:返回字符串的长度,如果参数s没有指定,则默认使用$0作为参数。

例如:

[kodango@devops ~]$ awk 'BEGIN {print length('kodango');}'0[kodango@devops ~]$ echo "first line" | awk '{print length();}'10

5.match(s, ere)

描述: 返回字符串s匹配ere的起始位置,如果不匹配则返回0。该函数会定义RSTART和RLENGTH两个内置变量。RSTART与返回值相同,RLENGTH记录匹配子串的长度,如果不匹配则为-1。

例如:

[kodango@devops ~]$ awk 'BEGIN {print match("kodango", /dango/);printf "Matched at: %d, Matched substr length: %d\n", RSTART, RLENGTH;}'3Matched at: 3, Matched substr length: 5

6.split(s, a[, fs])

描述:将字符串按照分隔符fs,分隔成多个部分,并存到数组a中。注意,存放的位置是从第1个数组元素开始的。如果fs为空,则默认使用FS分隔。函数返回值分隔的个数。

例如:

[kodango@devops ~]$ awk 'BEGIN {> split("1;2;3;4;5", arr, ";")> for (i in arr)> printf "arr[%d]=%d\n", i, arr[i];> }'arr[4]=4arr[5]=5arr[1]=1arr[2]=2arr[3]=3

这里有一个奇怪的地方是for..in..输出的数组不是按顺序输出的,如果要按顺序输出可以用常规的for循环:

[kodango@devops ~]$ awk 'BEGIN {> split("1;2;3;4;5", arr, ";")> for (i=0;^C[kodango@devops ~]$ awk 'BEGIN {> n=split("1;2;3;4;5", arr, ";")> for (i=1; i<=n; i++)> printf "arr[%d]=%d\n", i, arr[i];> }'arr[1]=1arr[2]=2arr[3]=3arr[4]=4arr[5]=5

7.sprintf(fmt, expr, expr, ...)

描述:类似printf,只不过不会将格式化后的内容输出到标准输出,而是当作返回值返回。

例如:

[kodango@devops ~]$ awk 'BEGIN {> var=sprintf("%s=%s", "name", "value")> print var> }'name=value

8.substr(s, m[, n])

描述:返回从位置m开始的,长度为n的子串,其中位置从1开始计算,如果未指定n或者n值大于剩余的字符个数,则子串一直到字符串末尾为止。

例如:

[kodango@devops ~]$ awk 'BEGIN { print substr("kodango", 2, 3); }'oda[kodango@devops ~]$ awk 'BEGIN { print substr("kodango", 2); }'odango

9.tolower(s)

描述:将字符串转换成小写字符。

例如:

[kodango@devops ~]$ awk 'BEGIN {print tolower("KODANGO");}'kodango

10.toupper(s)

描述:将字符串转换成大写字符。

例如

[kodango@devops ~]$ awk 'BEGIN {print tolower("kodango");}'KODANGO

I/O处理函数

1.getline

getline的用法相对比较复杂,它有几种不同的形式。不过它的主要作用就是从输入中每次获取一行输入。

a.expression | getline [var]

这种形式将前面管道前命令输出的结果作为getline的输入,每次读取一行。如果后面跟有var,则将读取的内容保存到var变量中,否则会重新设置$0和NF。

例如,我们将上面的statement.txt文件的内容显示作为getline的输入:

[kodango@devops awk_temp]$ awk 'BEGIN { while("cat statement.txt" | getline var) print var}' statementdeleteexitnext

上面的例子中命令要用双引号,"cat statement.txt",这一点同print/printf是一样的。

如果不加var,则直接写到$0中,注意NF值也会被更新:

[kodango@devops awk_temp]$ awk 'BEGIN { while("cat statement.txt" | getline) print $0,NF}' statement 1delete 1exit 1next 1

b.getline [var]

第二种形式是直接使用getline,它会从处理的文件中读取输入。同样地,如果var没有,则会设置$0,并且这时候会更新NF,NR和FNR:

[kodango@devops awk_temp]$ awk '{ > while (getline) > print NF, NR, FNR, $0;> }' statement.txt1 2 2 delete1 3 3 exit1 4 4 next

c.getline [var] < expression

第三种形式从expression中重定向输入,与第一种方法类似,这里就不加赘述了。

2.close

close函数可以用于关闭已经打开的文件或者管道,例如getline函数的第一种形式用到管道,我们可以用close函数把这个管道关闭,close函数的参数与管道的命令一致:

[kodango@devops awk_temp]$ awk 'BEGIN {while("cat statement.txt" | getline) { print $0; close("cat statement.txt");}}'statementstatementstatementstatementstatement

但是每次读了一行后,关闭管道,然后重新打开又重新读取第一行就死循环了。所以要慎用,一般情况下也很少会用到close函数。

3.system

这个函数很简单,就是用于执行外部命令,例如:

[kodango@devops awk_temp]$ awk 'BEGIN {system("uname -r");}'3.6.2-1-ARCH

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值