Skip to content

AWK的“自动换行”问题

五月 31, 2009
此为使用AWK处理某windows程序输出数据的时候发现的一个小问题,写下来记录备用。
我编写的代码的本意是将一个文本文件中的若干行的最后一个域(field)都放到最后一行输出,代码大概如下:

BEGIN{ORS="";}
#此语句的意思大概是设ORS(输出行间断符,见附录)为空,也就是说除非输出"\n",所有的print语句都将在同一行上输出。

x[i]=$2
#此处的$2为该行的最后一个域

END{ for(i in x){print x[i];} }
#语句的意思大概是在扫描文件结束后依次输出x数组中的数。

我想要的结果大概是:

hiya hiya hiya …

而实际上最后输出的(在文本编辑器gedit中)结果是:

hiya
 hiya
 hiya
 …

明明将ORS设成空的,怎么会自己换行呢?真是百思不得其解。然而,观察发现,在第一行输出之后,每一行输出的前面都会有一个空格(!)这正是AWK默认的OFS输出域分隔符,这说明AWK还是将这些hiya(……)当作一行中的不同域来处理的,莫非,是域内的数据被当作换行符了?突然想起来之前曾经读到过,M$和UNIXoid(……)系统的换行符体系不同,果然……

……实际上,Unix的换行符只有\n(Newline ASCII 为 10),而M$的换行符由\r(Carriage Return ASCII为13)和\n组成
然而,AWK的默认的RS(输入行间断符)依照unix格式是\n,因而AWK会认为\n前面的字元都是一行中的数据,从而将\r算作一行的最后一个域(field)的最后一个字元。这样一来,处理M$格式的数据时,虽然AWK自己显示的文件换行不会有问题(Carrige Return不会被显示出来),但如果使用兼容M$的编辑器打开的话,就可能发生\r被认作换行的情况,也就可能发生“自动”换行。

解决方法……
1 将RS(输入行间断符)设为M$兼容格式,RS="/r/n",这样一来,"/r"不会再被AWK认作是域的最后一个字元。这算是比较省心省事(只需要改BEGIN中的代码)的办法。或者……
2 用AWK将全文中的/r全部删掉……暴力办法,适于M$的坚决反对者们……

另(广告):AWK大概是世界上最古老同时又是最易用的计算机语言之一,对于很多任务而言,它可能仅仅只用几十行代码就可以进行可能要数千行C代码才能完成的工作。我的感觉是,你只要用它编出一个应用程序,就会彻底爱上它~

附:
FS
(Field separator) 输入域分隔符
RS (Record separator) 输入行分隔符
OFS (Output Field Separator) 输出域分隔符
ORS (Output Record Separator) 输出行分隔符
关于以上一些AWK标志位的教学,请参考IBM的develop liberary

Advertisements
No comments yet

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: