收藏 分销(赏)

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

上传人:xrp****65 文档编号:7684284 上传时间:2025-01-12 格式:DOC 页数:9 大小:44KB 下载积分:10 金币
下载 相关 举报
awk文本处理总结(入门中级高级).doc_第1页
第1页 / 共9页
awk文本处理总结(入门中级高级).doc_第2页
第2页 / 共9页


点击查看更多>>
资源描述
awk文本处理总结(入门,中级,高级) 作为技术支持工程我们最最经常的工作就是经常碰到要处理文本文件,不管是什么数据库最后都可以导成文本,我们就可以对他进行处理了,这样即使你不是对所有数据库操作都很熟悉也可以对他的数据进行处理了。     我们必须的工具有两个一个是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=" ;       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= 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=,o= uid: cailiying userPassword:: e21kNX0zREl4VEIwODBJdXZkTnU3WFFtS3lRPT0= letters: 300 quota: 100 dn: uid=caixiaoning,domain=,o= userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0= letters: 300 quota: 100 uid: chenzheng domain: dn: uid=caixiaoning,domain=,o= userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0= letters: 300 quota: 100 dn: uid=caixiaoning,domain=,o= userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0= letters: 300 quota: 100 uid: chenzheng domain:                                                                                     处理这个文本我们需要考虑的问题是: 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 { } 实际上对于学习语言首先是熟悉一些常用的函数,然后就是试着去解决别人解决过的问题,然后自己再思考一下是不是有更好,速度更快的解决办法,实际上大部分的程序员都是在重复的使用着别人好的解决办法,把别人的方法转变为自己的方法,就是反复练习解决不同的问题,思考更好的方法!                1 碰到一个问题是用户提供了一个文本包含 用户名:身份证号:单位 test:111222331222098:gongsi 要求用户名做为登陆名,身份证号的后三位做为登陆密码。 awk -F: '{ printf "%s:%s:%s\n",$1,$2,substr( $2, length($3)-2,length($3) ) }' txt   2 碰到的一个问题是awk处理两个数据文件 cat tmp1 qwe:rtgbh52800op poil:7851fghjj874 cat tmp2 poil:999rrr:66666 qwe:uytppp:77777   要求处理结果为 qwe:rtgbh52800op:77777 poil:7851fghjj874:66666   #!/bin/awk -f BEGIN {         FS=":";         i=1;         while((getline<"tmp2")>0)                 {F[i]=$1;S[i]=$3;i++}                 line=i; } {          for(j=1;j<=line;j++)                 { if($1==F[j])                         printf "%s:%s:%s\n",$1,$2,S[j];                 } } END {         print"END"; } #awk -f add.awk tmp1  处理完成
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 教育专区 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服