`

awk文本处理总结(入门,中级,高级)

阅读更多

 
awk处理文本总结 - Alex.Wang            2008-2-19 15:55

作为技术支持工程我们最最经常的工作就是经常碰到要处理文本文件,不管是什么数据库最后都可以导成文本,我们就可以对他进行处理了,这样即使你不是对所有数据库操作都很熟悉也可以对他的数据进行处理了。

我们必须的工具有两个一个是shell一个是awk,awk对于处理文本文件是最最适合的掌握了awk我们就可以很方便的处理文本文件再借助一些shell命令我们可以很方便得到自己想要的结果。现在从简单的例子来总结一下我觉得会经常碰到的问题。


--------------------------------------------------------------------------------

awk入门篇
 awk入门,文本内容example1.txt.
   
user1 password1 username1 unit1 10
user2 password2 username2 unit2 20
user3 password3 username3 unit3 30 

 

在unix环境中我们可以使用一下命令来打印出第一列
   
[root@mail awk]# awk '{print $1}' example1.txt

    得到的结果是如下,解释一下"'{" 单引号大括号包含awk语句是为了和shell 命令区别,$1的意思就是文本文件的第一列,正常的awk命令跟随-F参数指定间隔符号,如果是空格或tab键就可以省略了。   
user1
user2
user3 

[root@mail awk]# awk '{if($5>20) {print $1}}' example1.txt

        这行命令和上一行比较增加了“if($5>20)”,得到的结果是

user3

这个if语句就没有必要更详细的解释了吧!就是第5列大于20的显示出满足条件的第一列

[root@mail awk]# awk '{if($5>20 || $5==10) {print $1}}' example1.txt

user1
user3

在来一个初级的又增加了一个“if($5>20 || $5==10)”    做逻辑判断逻辑判断的三个“|| && !” 或、与、非三个可以任意加到里面,这个语句的意思是如果第5列大于20或者等于10的都显示处理,在我们的工作中可能有用户会要求找出所有空间大于多少的或者是空间等于多少的账户然后再做批量修改。

if是awk循环中的一个还有其他很多,man awk可以看到,
   Control Statements
       The control statements are as follows:

              if (condition) statement [ else statement ]
              while (condition) statement
              do statement while (condition)
              for (expr1; expr2; expr3) statement
              for (var in array) statement
              break
              continue
              delete array[index]
              delete array
              exit [ expression ]
              { statements }


学习awk可以经常使用一下man awk 可以看到所有的函数和使用方法。   

了解每个符号的意义我们才能更好的使用awk,最开始先记住几个命令知道他可实现的结果我们慢慢的再去理解。


--------------------------------------------------------------------------------

awk中级篇
这里顺便介绍一下vi的一个替换命令,现在我们要把example1.txt文本里的空格都替换为“:”冒号这里在vi里使用的命令就是:

%s/ /:/g     

这个命令对于使用vi的人来说是用得最多的。我们现在做了一个新的文件example2.txt。

user1:password1:username1:unit1:10
user2:password2:username2:unit2:20
user3:password3:username3:unit3:30

现在我们来做一个awk脚本,之前都是在命令行操作,实际上所有的操作在命令行上是可以都实现的,已我们最经常使用的批量添加用户来开始!

script1.awk

#!/bin/awk -f   # 当文件有可执行权限的时候你可以直接执行
                # ./script1.awk example2.txt
                # 如果没有以上这行可能会出现错误,或者
                # awk -f script1.awk example2.txt 参数f指脚本文件

BEGIN {         # “BEGIN{”是awk脚本开始的地方
    FS=":";     # FS 是在awk里指分割符的意思
}

{                                # 接下来的“{” 是内容部分
      print "add {";             # 以下都是使用了一个awk函数print
      print "uid=" $1;
      print "userPassword=" $2;
      print "domain=eyou.com" ;
      print "bookmark=1";
      print "voicemail=1";
      print "securemail=1"
      print "storage=" $5;
      print "}";
      print ".";
}                               # “}”    内容部分结束
END {                           # “END{” 结束部分
    print "exit";
}

执行结果
[root@mail awk]# awk -f script1.awk example2.txt
add {
uid=user1
userPassword=password1
domain=eyou.com
bookmark=1
voicemail=1
securemail=1
storage=10
}
.              
.
.
.
.
.
exit

文本操作就是更方便一些。

下面给两个返回效果一样的例子
[root@mail awk]# awk -F: '{print $1"@"$2}' example2.txt
[root@mail awk]# awk -F: '{printf "%s@%s\n",$1,$2}' example2.txt

user1@password1

这里的区别是使用print 和printf的区别,printf格式更自由一些,我们可以更加自由的指定要输出的数据,print会自动在行尾给出空格,而printf是需要给定" \n"的,如果感兴趣你可以把“\n”去掉看一下结果。%s代表字符串%d 代表数字,基本上%s都可以处理了因为在文本里一切都可以看成是字符串,不像C语言等其他语言还要区分数字、字符、字符串等。

awk还有一些很好的函数细细研究一下还是很好用的。


这次碰到了一个问题客户有一个用户列表,大概有2w用户,他有一个有趣的工作要做,就是把每个账户目录放到特定的目录下,例如13910011234这个目录要放到139/10/这个目录下,从这里可以看出规律是手机号码的前三位是二级目录名,手机的第3、4为是三级目录名,我们有的就只有一个用户列表,规律找到了我们现在开始想办法处理吧。

example3.txt

13910011234     
15920312343
13922342134
15922334422
......

第一步是要找到一个方法来吧,就是要把每一个手机号分开,最初可能你就会想到这个也没有任何间隔,我们怎么用awk分开他们呢?说实话最初我也考虑了20多分钟,后来想起原来学习python的时候有split函数可以分就想找找awk里是不是有类似的函数,man awk 发现substr 这个函数子串,

[root@mail awk]# awk '{print substr($1,1,3)}'  example3.txt

[root@mail awk]# awk '{printf "%s/%s\n",substr($1,1,3),substr($1,4,2)}'  example3.txt

[root@mail awk]# awk '{printf "mv %s %s/%s\n",$1,substr($1,1,3),substr($1,4,2)}'  example3.txt

以上的两步的返回自己做一下,最后我们就得到了我们想要的结果。

mv 13910011234 139/10
mv 15920312343 159/20
mv 13922342134 139/22
mv 15922334422 159/22

把这部分输出拷贝到一个shell脚本里,在数据当前目录下执行就可以了!

substr(s, i [, n])      Returns  the at most n-character substring of s
                               starting at i.  If n is omitted, the rest of  s
                               is used.
                              
substr函数解释,s代表我们要处理的字符串,i 是我们从这个字符串的第几个位置上开始,n 是我们从开始的位置取多少个字符。多看看man英文也会有所提高的。                              

awk有很多有趣的函数如果感兴趣可以自己去查查看,
man awk
String Functions  字符串函数,举几个觉得常用的函数
    length([s])             Returns  the  length  of  the  string s, or the
                               length of $0 if s is not supplied.
    length 你可以得到字符串的长度,这个是比较常用的一个函数                         
    split(s, a [, r])       Splits the string s into the  array  a  on  the
                               regular expression r, and returns the number of
                               fields.  If r is omitted, FS is  used  instead.
                               The   array  a  is  cleared  first.   Splitting
                               behaves   identically   to   field   splitting,
                               described above.    
                              
        tolower(str)            Returns  a copy of the string str, with all the
                               upper-case  characters  in  str  translated  to
                               their  corresponding  lower-case  counterparts.
                               Non-alphabetic characters are left unchanged.
                              
        toupper(str)            Returns a copy of the string str, with all  the
                               lower-case  characters  in  str  translated  to
                               their  corresponding  upper-case  counterparts.
                               Non-alphabetic characters are left unchanged.
                                                                                    Time Functions  时间函数,我们最最常用到的是时间戳转换函数
                                                                                  
strftime([format [, timestamp]])
                 Formats  timestamp  according to the specification in format.
                 The timestamp should be of the same form as returned by  sys-
                 time().   If timestamp is missing, the current time of day is
                 used.  If format is missing, a default format  equivalent  to
                 the output of date(1) is used.  See the specification for the
                 strftime() function in ANSI C for the format conversions that
                 are  guaranteed  to be available.  A public-domain version of
                 strftime(3) and a man page for it come  with  gawk;  if  that
                 version  was  used to build gawk, then all of the conversions
                 described in that man page are available to gawk.                                                                                  
                                                                                  
这里举例说明时间戳函数是如何使用的

[root@ent root]# date +%s | awk '{print strftime("%F %T",$0)}'
2008-02-19 15:59:19        

我们先使用date命令做一个时间戳,然后再把他转换为时间                                                                                             
还有一些我们现在可能不经常用到的函数,详细内容man awk 自己可以看一下。
 Bit Manipulations Functions   二进制函数
 Internationalization Functions  国际标准化函数
 
 USER-DEFINED FUNCTIONS      用户也可以自己定义自己的函数,感兴趣自己可以再深入研究一下。
 
 For example:

              function  f(p, q,     a, b)   # a and b are local
              {
                   ...
              }

              /abc/     { ... ; f(1, 2) ; ... }
 DYNAMICALLY LOADING NEW FUNCTIONS  动态加载新函数,这个可能就更高级一些了!


--------------------------------------------------------------------------------

 awk高级篇
 
 不管学习任何语言,我们学到的都是工具,工具知道的越多,我们做起工作来就越方便,但是工具在你的手里并不一定能造出好的产品,编辑脚本和编程序也是一样的重要的是算法,别人不知道怎么处理的问题你要知道如何处理。这才能证明你比别人更高,工具只要你慢慢练习都会使用。
 
    下面给大家一个我认为是比较高级的问题了,感兴趣的可以自己再想想更好的解决办法。问题是这样的我们有一个从ldap里导出的文件,它都是一行一个字段来说明的,每个用户的数据是已空行分割的。我们必须把对应的uid 和userPassword找出来而且是对应的。
   
    例子:example4.txt
   
dn: uid=cailiying,domain=ccc.com.cn,o=mail.ccc.com.cn
uid: cailiying
userPassword:: e21kNX0zREl4VEIwODBJdXZkTnU3WFFtS3lRPT0=
letters: 300
quota: 100

dn: uid=caixiaoning,domain=ccc.com.cn,o=mail.ccc.com.cn
userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0=
letters: 300
quota: 100
uid: chenzheng
domain: cqc.com.cn

dn: uid=caixiaoning,domain=ccc.com.cn,o=mail.ccc.com.cn
userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0=
letters: 300
quota: 100

dn: uid=caixiaoning,domain=ccc.com.cn,o=mail.ccc.com.cn
userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0=
letters: 300
quota: 100
uid: chenzheng
domain: cqc.com.cn
                                                                                    处理这个文本我们需要考虑的问题是:
1 uid  和userPassword 并不是每一个段落里都有
2 在每一段里面uid和userPassword 先后顺序是随机的
3 有的段落里可能只有uid 或者只有userPassword

从文本上分析可以看出必须使用的间隔符号,一个是空行,一个是冒号。
冒号我们awk -F:就可以了,不过空行我们不好判断现在想到length()这个函数,在unix里空行最多只有一个\n字符,如果一行字符数小于2我们判断为空行,好现在间隔符号问题解决,空行只能通过循环来实现对空行的判断。                                        

现在碰到的另外一个问题是我们的某个段里的信息是不完全的,我们就要放弃这段这儿如何来做,就是要做两个标记变量u 和 p  再做一个循环如果u  和  p 同事满足我们才输出结果下面的awk脚本就是通过这个思考来解决ldif文本的处理的!

# 此脚本的目的是方便我们以后导ldap的其他邮件的数据,
# 我们之前使用slapdcat -l 导出所有信息,然后我们需要
# 整理出uid  password , 这里的设置都是默认以":" 间隔的
# 例slapcat -l user.ldif  如果想得到一份uid 和userPassword 对应的文件,
# 修改username = "dn"; password = "userpassword"; awk -f ldap2txt.awk user.ldif | grep uid | more  可以查看结果 (有可能是多域的邮件)
# 如果想得到domain 所对应的密码,修改username = "dn"; password = "userpassword";  运行 awk -f ldap2txt.awk user.ldif |grep domain | more


#!/bin/awk -f
# File name: ldap2txt.awk

BEGIN {
        FS = ":";
        username = "uid";
        password = "userPassword";
}

{

        if(length($0) == 0 )
        {
                if (name != "u"  &&  pword != "p")
                {
                        printf ("%s:%s\n", name,pword);
                        name = "u";
                        pword = "p";
                }
        }

        else 
        {
                if ($1 == username)
                {
                name = "u";
                name = $0;
                }
                else if($1 == password)
                {
                pword = "p";
                pword = $0;
                }
        }
}
END {

}

实际上对于学习语言首先是熟悉一些常用的函数,然后就是试着去解决别人解决过的问题,然后自己再思考一下是不是有更好,速度更快的解决办法,实际上大部分的程序员都是在重复的使用着别人好的解决办法,把别人的方法转变为自己的方法,就是反复练习解决不同的问题,思考更好的方法!


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/blackbillow/archive/2009/01/21/3847425.aspx

分享到:
评论
1 楼 sn201 2012-03-07  
awk高级篇
有问题啊!有问题!有问题!有问题!有问题!

if(length($0) == 0)
{
if(name != "u" && pword != "p")
{
printf("%s:%s \n",name,pword);
}
// 每一次遇到空行之后 都应该把name,pword重置
name = "u";
pword = "p";
example4.txt
特别注意这个文本的最后要加上一个空行,不然最后一条没法输出。

相关推荐

    AWK文件处理总结

    awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理awk文本的处理

    awk文本处理工具

    linux运维,文本处理三剑客之,awk文本处理工具。非常详细!

    awk文本处理工具命令详解

    awk是强大的文本处理工具,awk提供了极其强大的功能:它几乎可以完成grep和sed所能完成的全部工作。

    shell awk脚本总结.txt

    我们必须的工具有两个一个是shell一个是awk,awk对于处理文本文件是最最适合的掌握了awk我们就可以很方便的处理文本文件再借助一些shell命令我们可以很方便得到自己想要的结果。现在从简单的例子来总结一下我觉得会...

    awk入门级教材awk入门awk入门

    awk 是一门编程语言,它的基本操作是在一组文件上查找模式,并在包含这些模式实例的那 些行或字段上进行指定的动作。awk 使得特定数据的选择和变换操作更易于表达

    awk基本入门和高级用法

    awk学习快速入门、基本用法、高级应用。基本入门说明使用的基本方法;高级应用主要是管道的用法

    Linux下对NS2项目的仿真分析全过程(从tcl脚本-awk文本处理-gnuplot)

    Linux下对NS2项目的仿真分析全过程的代码(从tcl脚本-awk文本处理-gnuplot) 运行过程详见本人CSDN中的描述

    awk脚本学习快速入门

    收集的awk脚本学习 快速入门 包含sed 和正则表达式 不好用 别下 我重新上传

    awk编程语言入门

    awk编程语言入门--awk是linux下的一个命令,他对其他命令的输出,对文件的处理都十分强大,其实他更像一门编程语言,他可以自定义变量,有条件语句,有循环,有数组,有正则,有函数等。

    awk教程入门到精通

    awk完整教程 0基础入门到精通 awk完整教程 0基础入门到精通

    linux 文本处理 awk 手册

    awk 是一种程序语言. 它具有一般程序语言常见的... 此外, awk内建有pipe的功能, 可将处理中的数据传送给外部的 Shell命令加以处理, 再将Shell命令处理后的数据传回awk程序, 这个特点也使得awk程序很容易使用系统资源.

    awk入门到精通.pdf

    awk在linux系统下的使用必不可少。 awk 是一种程序语言. 它具有一般程序语言常见...本手册为awk入门的学习指引, 其内容将先强调如何撰写awk程序,未列入进一步解题方式的应 用实例, 这部分将留待UNIX进阶手册中再行讨论.

    关于awk的用法总结

    在shell 编程中,常需要用awk ,可以非常方便的解决些需求,这是一个关于awk的用法总结!

    用awk数组处理两个文件

    主要讲解了关于shell中用awk数组处理文件的用法

    教你如何使用 awk 处理文本内容.doc

    Awk是为高级文本处理而设计的非常强大的工具。它逐行搜索扫描文件,将输入的每行分割成字段,将输入行或字段与模式进行比较,并对匹配的结果执行操作。

    AWK是一种优良的文本处理工具

    最简单地说, AWK 是一种用于处理文本的编程语言工具。AWK 在很多方面类似于 shell 编程语言,尽管 AWK 具有完全属于其本身的语法。它的设计思想来源于 SNOBOL4 、sed 、Marc Rochkind设计的有效性语言、语言工具 ...

    巧用AWK处理二进制数据文件

    awk是unix,linux中处理文本的好工具,本文用一个实例说明awk脚本的编写及使用.

    awk实例入门教程.pdf

    awk 实例入门 教程 AWK_样式扫描和处理语言

Global site tag (gtag.js) - Google Analytics