当前位置: 首页 > news >正文

shell学习笔记2---awk字符串处理(原创)

awk内置字符串函数
gsub(r,s) 在整个$0中用s替代r;gsub(r,s,t) 在整个t中用s替代r

gsub函数有点类似于sed查找和替换。它允许替换一个字符串或字符为另一个字符串或字符,并以正则表达式的形式执行。第一个函数作用于记录$0,第二个gsub函数允许指定目标,然而,如果未指定目标,缺省为$0。
index(s,t):函数返回目标字符串s中查询字符串t的首位置。
length(s) :返回s长度
match(s,r): 测试s是否包含匹配r的字符串
split(s,a,fs) 在fs上将s分成序列a
sprint (fmt,exp) :函数类似于printf函数(以后涉及),返回基本输出格式fmt的结果字符串exp。
sub(r,s) 用$0中最左边最长的子串代替s
substr(s,p) 返回字符串s中从p开始的后缀部分
substr(s,p,n) 返回字符串s中从p开始长度为n的后缀部分。
match函数测试字符串s是否包含一个正则表达式r定义的匹配。
split使用域分隔符fs将字符串s划分为指定序列a。
1.gsub
要在整个记录中替换一个字符串为另一个,使用正则表达式格式, /目标模式/,替换模式/。例如改变学生序号4842到4899:

$cat grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99   4712 Brown-2 12 30 28
# cd /usr/sam
# awk 'gsub(/4842/,4899){print $0}' grade.txt
J.Troll 07/99 4899 Brown-3 12 26 26
2. index
查询字符串s中t出现的第一位置。必须用双引号将字符串括起来。例如返回目标字符串Bunny中ny出现的第一位置,即字符个数。
# awk 'BEGIN {print index("Bunny","ny")}' grade.txt
4
3. length
返回所需字符串长度,例如检验字符串J.Troll返回名字及其长度,即人名构成的字符个数
# awk '$1=="J.Troll" {print length($1)" "$1}' grade.txt
7 J.Troll
还有一种方法,这里字符串加双引号。
# awk 'BEGIN{print length("A FEW GOOD MEN")}'
14
4. match
match测试目标字符串是否包含查找字符的一部分。可以对查找部分使用正则表达式,返回值为成功出现的字符排列数。如果未找到,返回0,第一个例子在ANCD中查找d。因其不存在,所以返回0。第二个例子在ANCD中查找D。因其存在,所以返回ANCD中D出现的首位置字符数。第三个例子在学生J.Lulu中查找u。
# awk 'BEGIN{print match("ANCD",/d/)}'
0
# awk 'BEGIN{print match("ANCD",/D/)}'
4
# awk '$1=="J.Lulu" {print match($1,"u")}' grade.txt
4
5. split
使用split返回字符串数组元素个数。工作方式如下:如果有一字符串,包含一指定分隔符-,例如AD2-KP9-JU2-LP-1,将之划分成一个数组。使用split,指定分隔符及数组名。此例中,命令格式为("AD2-KP9-JU2-LP-1",parts_array,"-"),split然后返回数组下标数,这里结果为4。
# awk 'BEGIN {print split("123-456-789",pats_array,"-")}'
3
还有一个例子使用不同的分隔符。
# awk 'BEGIN {print split("123#456#789",myarray,"#")}'                    
3
这个例子中,split返回数组myarray的下标数。数组myarray取值如下:
myarray[1]=123
myarray[2]=456
myarray[3]=789
6. sub
使用sub发现并替换模式的第一次出现位置。字符串STR包含'poped popo pill',执行下列sub命令sub(/op/,"OP",STR)。模式op第一次出现时,进行替换操作,返回结果如下:'pOPed pope pill'。
如:学生J.Troll的记录有两个值一样,"目前级别分"与"最高级别分"。只改变第一个为29,第二个仍为26不动,操作命令为sub(/26/,"29",$0),只替换第一个出现26的位置。注意J.Troll记录需存在。
# awk '$1=="J.Troll" sub(/26/,"29",$0)' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 29
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 29 26
L.Tansl 05/99 4712 Brown-2 12 30 28
7. substr
substr是一个很有用的函数。它按照起始位置及长度返回字符串的一部分。例子如下:
# awk '$1=="L.Tansl" {print substr($1,1,3)}' grade.txt
L.T
上面例子中,指定在域1的第一个字符开始,返回其前面3个字符。
如果给定长度值远大于字符串长度, awk将从起始位置返回所有字符,要抽取LTansl-ey的姓,只需从第3个字符开始返回长度为7。可以输入长度99,awk返回结果相同。
# awk '$1=="L.Tansl" {print substr($1,1,99)}' grade.txt
L.Tansl
substr的另一种形式是返回字符串后缀或指定位置后面字符。这里需要给出指定字符串及其返回字串的起始位置。例如,从文本文件中抽取姓氏,需操作域1,并从第三个字符开始:
# awk '{print substr($1,3)}' grade.txt
Tans
Lulu
Bunny
Troll
Tansl
还有一个例子,在BEGIN部分定义字符串,在END部分返回从第t个字符开始抽取的子串。
# awk 'BEGIN{STR="A FEW GOOD MEN"}END{print substr(STR,7)}' grade.txt
GOOD MEN
8. 从shell中向awk传入字符串
awk脚本大多只有一行,其中很少是字符串表示的。大多要求在一行内完成awk脚本,这一点通过将变量传入awk命令行会变得很容易。现就其基本原理讲述一些例子。
使用管道将字符串stand-by传入awk,返回其长度。
# echo "Stand-by" | awk '{print length($0)}'
8
设置文件名为一变量,管道输出到awk,返回不带扩展名的文件名。
# STR="mydoc.txt"
# echo $STR|awk '{print substr($STR,1,5)}'
mydoc
设置文件名为一变量,管道输出到awk,只返回其扩展名。
# STR="mydoc.txt"
# echo $STR|awk '{print substr($STR,7)}'
txt

字符串屏蔽序列
使用字符串或正则表达式时,有时需要在输出中加入一新行或查询一元字符。打印一新行时(新行为字符\n),给出其屏蔽序列,以不失其特殊含义,用法为在字符串前加入反斜线。例如使用\n强迫打印一新行。
如果使用正则表达式,查询花括号({ }),在字符前加反斜线,如/\{/,将在awk中失掉其特殊含义。
awk中使用的屏蔽序列
\b 退格键
\t tab键
\f 走纸换页
\ddd 八进制值
\n 新行
\c 任意其他特殊字符,例如\ \为反斜线符号
\r 回车键
使用上述符号,打印May Day,中间夹tab键,后跟两个新行,再打印May Day,但这次使用八进制数104、141、171分别代表D、a、y。
# awk 'BEGIN {print"\nMay\tDay\n\nMay\t\104\141\171"}'

May     Day

May     Day
注意,\104为D的八进制ASCII码,\141为a的八进制ASCII码,等等。
awk输出函数printf
目前为止,所有例子的输出都是直接到屏幕,除了tab键以外没有任何格式。awk提供函数printf,拥有几种不同的格式化输出功能。例如按列输出、左对齐或右对齐方式。
每一种printf函数(格式控制字符)都以一个%符号开始,以一个决定转换的字符结束.转换包含三种修饰符。
printf函数基本语法是printf([格式控制符],参数),格式控制字符通常在引号里。
printf修饰符
-                 左对齐
Width         域的步长,用0表示0步长
.prec          最大字符串长度,或小数点右边的位数
awk printf格式
%c            ASCII字符
%d           整数
%e           浮点数,科学记数法
%f            浮点数,例如(1 2 3 . 4 4)
%g           awk决定使用哪种浮点数转换e或者f
%o           八进制数
%s           字符串
%x           十六进制数
1. 字符转换
观察ASCII码中65的等价值。管道输出65到awk。printf进行ASCII码字符转换。这里也加入换行,因为缺省情况下printf不做换行动作。
$echo "65" | awk '{printf "%c\n",$0}'
A
按同样方式使用awk得到同样结果。
$awk 'BEGIN{printf "%c\n",65}'
A
所有的字符转换都是一样的,下面的例子表示进行浮点数转换后'999'的输出结果。整数传入后被加了六个小数点。
$awk 'BEGIN{printf "%f\n",999}'
999.000000
2. 格式化输出
打印所有的学生名字和序列号,要求名字左对齐, 15个字符长度,后跟序列号。注意\n换行符放在最后一个指示符后面。输出将自动分成两列。
# awk '{printf "%-15s %s\n",$1,$3}' grade.txt
M.Tans          48311
J.Lulu          48317
P.Bunny         48
J.Troll         4842
L.Tansl         4712
加入一些文本注释帮助理解报文含义。可在正文前嵌入头信息。注意这里使用print加入头信息。如果愿意,也可使用printf。
# awk 'BEGIN{print "Name\t\tS.Number"}{printf "%-15s %s\n",$1,$3}' grade.txt
Name            S.Number
M.Tans          48311
J.Lulu          48317
P.Bunny         48
J.Troll         4842
L.Tansl         4712
打印输出“What is your name?" 利用getline函数从终端接收输入,并传送给name变量,直到用户输入回车为止,如果第一域匹配employees2中的记录。
打印“Found ",name变量,"on line" ,行号。
打印“See ya, ”,name变量
以上是传入name变量的值存在于employees2中的情况
$ awk 'BEGIN{printf "What is your name?" ;\
getline name < "/dev/tty"}\
$1 ~ name {print "Found " name " on line ",NR "."}\
END{print "See ya, " name "."}' employees2
What is your name?Tom
Found Tom on line 1.
See ya, Tom.
不存在于employees2中的情况
$ awk 'BEGIN{printf "What is your name?" ;\
getline name < "/dev/tty"}\
$1 ~ name {print "Found " name " on line ",NR "."}\
END{print "See ya, " name "."}' employees2
What is your name?czm
See ya, czm.

 

参考至:《UNIX® Shells by Example Fourth Edition》By Ellie Quigley 
                  《LINUX与UNIX SHELL编程指南》
                 http://blog.sina.com.cn/s/blog_45b28bfb0100o0fs.html

本文为原创文章,转载请注明出处、作者

如有错误,欢迎指正

邮箱: czmcj@163.com

作者:czmmiao  文章出处:http://czmmiao.iteye.com/blog/1885280

相关文章:

  • 各主流浏览器的区别
  • java获取真实ip地址
  • 简单查询(1)
  • 详解Zoosk千万用户实时通信背后的开源技术[转]
  • 【转】jvm 内存模型及内存调优
  • UESTC 75 The Queen's New Necklaces
  • 冯·若依曼体系结构
  • MySQL学习总结(二)数据库以及表的基本操作
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • Swift 中的尾递归和蹦床
  • 关于学习了《构建之法》的若干存在疑惑的问题
  • spring 整合 struts
  • open-falcon+grafana出图
  • C语言应用-飞机游戏
  • 第二阶段冲刺第八天
  • 2017届校招提前批面试回顾
  • Angular 响应式表单 基础例子
  • Bootstrap JS插件Alert源码分析
  • C# 免费离线人脸识别 2.0 Demo
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • C++入门教程(10):for 语句
  • httpie使用详解
  • JSONP原理
  • js对象的深浅拷贝
  • leetcode386. Lexicographical Numbers
  • mac修复ab及siege安装
  • Material Design
  • maya建模与骨骼动画快速实现人工鱼
  • PAT A1120
  • PHP变量
  • socket.io+express实现聊天室的思考(三)
  • Theano - 导数
  • Zepto.js源码学习之二
  • 百度地图API标注+时间轴组件
  • 对超线程几个不同角度的解释
  • 分布式任务队列Celery
  • 回顾2016
  • 深度解析利用ES6进行Promise封装总结
  • 深度学习中的信息论知识详解
  • 手写一个CommonJS打包工具(一)
  • 我的zsh配置, 2019最新方案
  • 一道面试题引发的“血案”
  • 运行时添加log4j2的appender
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 【干货分享】dos命令大全
  • 翻译 | The Principles of OOD 面向对象设计原则
  • ​如何在iOS手机上查看应用日志
  • #Ubuntu(修改root信息)
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (23)Linux的软硬连接
  • (多级缓存)缓存同步
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (六)激光线扫描-三维重建
  • (算法)前K大的和