AWK编程--不仅仅是一条命令

作者: 赵燕燕

(一)AWK

Linux下有很多基于文本的样式扫描和处理的工具,他们可以实现以文档的列或行为单位进行扫描处理,大大减轻了文本处理的工作量, 这样的命令包括sed, grep, sort以及find等等,awk是其中很优秀的一种。他的功能大大强于sedgrep.它不仅可以完成grepsed所能完成的全部工作,还可以进行样式装入,流控制,数学运算,进程控制甚至变量和函数。awk不仅是一条命令,更是一种语言。

awk特别适合于重新格式化数据文件,它可以将输入数据分成若干个记录,每个记录可以分成以特定分割符分开的域,这样对于任何域都可以灵活的操作处理。 而且awk的语法又和shellC有很多相似之处,便于学习。

下面的章节就简单得从变量, 命令格式,子函数等几个方面详细的介绍下awk.

(二)AWK的格式:

awk Option ' 'BIGIN' {动作语法} {动作语法}  'END' {动作语法}' file1 file2 …

 

1)         Option

Option指的是awk执行单引号部分之前进行的操作

-f: 运行awk文件

例如:awk -f filename

-F: 设置分隔符,

例如,设置分割符为 “|”

awk –F “|” ‘{print $1}’ filename

-v:  特殊操作,需要在执行单引号部分之前就执行的

例如,传递shell参数:awk -v var=$b '{print var, $var}' filename

 

2) BEGIN

BEGIN是要在执行行处理之前就执行的,执行的动作用{}括起来。注意,此处awk并没有读入文档,也不知道要处理的文档的名字信息,关于文档的变量都被设置为null

 

3END

END是要在执行行处理之后执行的,所有变量的值都和处理完文档的值保持一致。执行的动作用{}括起来

 

4)行处理的动作:

行处理的动作夹在BEGIN{}END{}之间, 可以包括模式匹配和行处理动作。 其中行处理动作要用{}括起来。模式匹配不包含在{}之中。

  模式匹配:支持正则表达式的匹配

  例如:awk ‘/^8*/’ file

        awk ‘$2 >5 && $2<=15’ file

        awk '$1 ~ /101/ {print $1}' file 匹配后执行动作

        awk '$1>2 {print $1,$2}' file匹配后执行动作

  行处理动作:包括字符串操作,数字操作等等。

而且数字操作可以实现数字和字符串的直接运算。

  例如:awk -v s=123 '{n = 0 + s; print n}' filename

如果字符串不是以数字开头的,例如sads222, 就直接默认为这个变量为0

如果字符串以数字开头,例如233asd,就直接截取数字的部分。

 

行处理动作的awk语法中循环,判断,输出等都与C语言很接近。这也是awk受到欢迎的一个原因。

例如: 找到以|分隔的test.txt文件中的第一列是以8开头的行数

     awk -F | ''BEGIN'{d=0} /$1~^8/{d++} 'END'{print d}' filename

   单引号的部分都可以完全放入到.awk的文件中

 上面的命令行的例子,同样可以在文件中实现:

 例如:可以编写file.awk

   BEGIN {d=0}

   /$1~^8/{d++}

   END {print d}

   运行awk命令: awk -f file.awk test.txt  

(三)AWK的变量

1) 内置变量:

shell语言一样,awk有一些内置变量。 这些变量使用户可以方便的控制想要获取的文件的属性信息:

$1, $2....处理行的第一列,第二列...

$0处理行的所有列

ARGC 命令行参数个数
ARGV
命令行参数排列
ENVIRON
支持队列中系统环境变量的使用
FILENAME awk
浏览的文件名
FNR
浏览的文件名
FS
设置输入域分隔符,等价于命令行-F选项
NF
浏览记录的域个数
NR
已读的记录数
OFS
输出域分隔符
ORS
输出记录分隔符
RS
控制记录分隔符

例如:打印域的个数,已读的记录数,整行信息,第一个参数(0的话是全部)及用户(最后一个是取得系统的环境变量)

       awk -F '#' '{print NF,NR,$0,ARGV[1]ENVIRON["USER"]}' test.txt

 

2) 变量

变量的表示基本与shell保持一致。任何定义的变量不需要初始化,awk会根据第一次定义的数值,确定类型。

3) 输入输出

 输入:awk '/^8/{"echo '$1'"|getline d; print d}' test.txt

    awk ‘BEGIN {“date”|getline d; print d}'

    echo aaas | awk '{print $1}'

  其他的awk引用外部变量的几种方法:

a.       awk –v awkvar=$extvar…#使外部变量的作用域扩展到BEGIN{}

b.      awk '<awk expression>' "awkvar=$extvar" filename #BEGIN段不可用

c.        awk表达式中使用'$extvar'

d.      模式引用(在正则表达式中引用外部变量) '"$extvar"

e.       遍历外部数组(用于BEGIN段处理) awk 'BEGIN{for(i=1;i<ARGC;i++)print ARGV[i]}' ${extarr[@]}

f.       引用环境变量 ENVIRON["environment variable"]

例如:awk中引用shell的变量

export变量,然后用ENVIRON“var”
#!/bin/bash
var="test"
export var
awk 'BEGIN{print ENVIRON["var"]}'
使用-v选项。
#!/bin/bash
var="test"
awk -v nvar="$var" 'BEGIN{print nvar}'

使用" "

awk '{print awkvar}' "awkvar=$var" filename

使用' '

awk '{print '$var'}' filename

 

例如:Shell中使用awk传递出来的变量

eval $(awk 'BEGIN{print "var1=along;var2=test"}')
echo "var1:"$var1
echo "var2:"$var2

 输出:print echo,重定向...

(四)子函数

子函数的定义与C, C++等其他的语言的定义是一致的

例如一个awk可以写成:

function gcd(x, y)

{

        x = int(x)

        y = int(y)

        print x,y

        r = x % y

        return (r == 0)? y : gcd(y, r)

}

BEGIN {print "BEGIN"}

{g = gcd($1, $2); print "gcd("$1" ,"$2") =",g}

END {print "END"}

 

 

避免变量污染,可以在子函数中使用局部变量。例子中function factorial(n, i)i就是在定义局部变量,n是从主函数中传递过来的值。

function factorial(n, i)

{

s=1;

for (i=1; i<=n; i++)

{

s*=i;

}

return s;

}

{

for (i=1;i<=10;i++)

{

value=factorial(i);

printf("fac(%d)=%d/n",i,value);

}

}

同样可以这样定义: function factorial(n, _ARGVEND_, i), 其中的_ARGVEND_的表示正常的调用所需要的形参到此结束。后面的假形参只是局部变量的定义。

(五)调试

Awk可以简单的作为单条的命令并结合输入输出,进行调试。

另外,如果想要查看运行中调试全局变量, 可以使用-dump-variables 参数。 例如调用上面的文件:echo "" | awk -f fac.awk --dump-variables=/tmp/var.dump

查看var.dump文件,就会把所有的属性信息,变量信息打印出来

ARGC: number (1)

ARGIND: number (0)

ARGV: array, 1 elements

BINMODE: number (0)

CONVFMT: string ("%.6g")

ERRNO: number (0)

FIELDWIDTHS: string ("")

FILENAME: string ("-")

FNR: number (1)

FS: string (" ")

IGNORECASE: number (0)

LINT: number (0)

NF: number (0)

NR: number (1)

OFMT: string ("%.6g")

OFS: string (" ")

ORS: string ("/n")

RLENGTH: number (0)

RS: string ("/n")

RSTART: number (0)

RT: string ("/n")

SUBSEP: string ("/034")

TEXTDOMAIN: string ("messages")

i: number (11)

s: number (3628800)

value: number (3628800)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值