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

17.文本处理工具awk awk是基于列的文本处理工具,awk认为文件都是结构化的,也就是说都是由单词和各种空白字符组成的,这里的“空白字符”包括空格、TAB以及连续的空格和TAB等。每个非空白的部分叫做“域”从左到右依次是第一个域第二个域等。$1、$2分别用于表示域,$0则表示全部域。printf:可以自定义输出的模式,另外输出内容之后不自动换行,print:输出内容之后自动换行。print 中不能使用%s ,%d 或%c。 阅读详情

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 {

}

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

awk man中文手册(全) awk man中文手册(全) awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。 立即下载

相关推荐

awk手册中文版-全面实用

awk:超级强大的linux/unix下的文本处理语言,处于linux/unix工程师必知必会的东东。这版手册内容很全,比我手头的《UNIX和LINUX权威教程》上的awk部分还要全面。

awk 4.0+ man手册翻译第一版本

CentOS 7 上awk 4.0以上版本的man手册翻译第一版: 参考地址:http://www.cnblogs.com/wutao666/p/9732976.html 参考地址:https://www.gnu.org/software/gawk/manual/gawk.html#Array-Sorting GAWK(1) Utility Commands GAW...

u012271055的专栏 3229

Containerd容器运行时的私有仓库镜像推送push和镜像拉取问题解决

向/etc/containerd/config.toml配置添加如下配置,然后重启containerd。向/etc/containerd/config.toml配置添加如下配置,然后重启containerd。通过crictl为k8s拉取镜像如下所示。可以通过ctr命令进行镜像推送。往私有仓库推送镜像如下。

Bulut0907 1万+

收集整理的awk用法小结

收集整理的awk用法小结 By Michael提示:其实 man awk 提供的文档也很详细,不过整理加上中文估计还是可以对初学者有一定帮助的。awk 用法:awk ‘ pattern {action} ‘ 变量名 含义ARGC 命令行变元个数ARGV 命令行变元数组FILENAME 当前输入文件名FNR 当前文件中的记录号FS 输入域分隔符,默认为一个空格RS 输入记录分隔符

在水一方 783

Golang面试(一)莉莉丝游戏-Golang后端开发-中台部门

莉莉丝游戏-Golang后端开发-中台部门 开场白,双方自我介绍,对方介绍这个岗位情况,erlang语言,全部转向go。 聊项目,介绍IM架构以及使用Go写的服务简介 动态扩容相关问题:平常30万,现在100万,你们现在是如何应对的? 如果让你调整架构实现动态扩容,你会怎么做?回答了kafka,是一种,应该还要使用docker和k8s以及微服务框架等 如果使用kafka,你是如何确保消息有序?回答了redis,好像没回答到那个点 消息发送失败的问题,如何做到消息不丢?回答持久化存储、拉消息和ACK 发送失

xmcy001122的专栏 3899

CANoe UDS $27服务DLL生成实战:从工程配置到算法修改全流程

本文详细介绍了在Vector CANoe中为UDS(统一诊断服务)的$27安全访问服务生成定制化DLL(动态链接库)的全流程。从定位官方参考工程、配置Visual Studio开发环境,到深入解析核心的GenerateKeyEx函数接口,并重点演示了如何修改和实现自定义的种子-密钥安全算法,最终完成DLL的编译、部署与CANoe集成测试,为汽车电子诊断开发提供实战指导。

star5的专栏 535

awk文本处理总结

 awk文本处理总结(入门,中级,高级)   awk处理文本总结 - Alex.Wang            2008-2-19 15:55          作为技术支持工程我们最最经常的工作就是经常碰到要处理文本文件,不管是什么数据库最后都可以导成文本,我们就可以对他进行处理了,这样即使你不是对所有数据库操作都很熟悉也可以对他的数据进行处理了。    我们必须的工具有两个一个是shell

红杉树(ecitnet)的博客 4546

Yolov5s可视化网络结构图

Yolov5共有四种网络结构,每种网络深度和宽度上都不相同。 (1) Yolov5s可视化网络结构图:点击查看 (2) Yolov5m可视化网络结构图:点击查看 (3) Yolov5l可视化网络结构图:点击查看 (4) Yolov5x可视化网络结构图:点击查看 ...

江南研习社 15万+

awk命令详解

awk文本处理总结(入门,中级,高级)  作为技术支持工程师,我们最最经常的工作就是要处理文本文件,不管是什么数据库最后都可以导成文本,我们就可以对他进行处理了,这样即使你不是对所有数据库操作都很熟悉,也可以对他的数据进行处理了。 我们必须的工具有两个:一个是shell,一个是awk。awk对于处理文本文件是最最适合的,掌握了awk我们就可以很方便的处理文本文件;再

知行合一 709

Ubuntu20.04下运行VINS系列:VINS-Mono、VINS-Fusion和GVINS

安装好了VINS-Mono所需的ROS noetic、Eigen3.4.0、Ceres2.10和OpenCV4.2.0等。VINS-Mono是在ROS melodic以及Ceres1的环境下开发的,因此需要适配高版本的环境。

zardforever123的博客 2万+

RK3568_Android15适配以太网网卡gmac+国产phy芯片YT8531

本文介绍了在Android15 SDK上适配正点原子ATK-DLRK3568开发板网卡的过程。开发板采用GMAC接口搭配YT8531C PHY芯片,包含两个千兆网口。主要内容包括:硬件原理图确认、网络链路连接方式、内核DTS配置(包括GMAC0和GMAC1的参数设置)、PHY驱动适配(基于motorcomm.c驱动文件)、PHY寄存器读写调试方法以及MAC地址设置方式。文章还分析了常见问题,如网卡注册后无法ping通网络的故障现象。通过详细的硬件确认和软件配置,实现了双网卡在Android系统上的完整适配。

Android/Linux驱动开发传帮带学习,让驱动入门门槛更低! 2015
上一篇: Shell 变量
下一篇: ASCII码对照表
jjaing
博客等级 码龄23年 3粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值