Linux awk -F 命令如何指定输出awk 去除双引号号里的内容,求助

例子: 例1:替换分隔符
time="12:34:56"
out=`echo $time | awk '{split($0,a,":");print a[1],a[2],a[3]}'`
&例2:计算指定范围内的和(计算每个人1月份的工资之和)
[root@test ~]# cat test.txt
[root@test ~]# awk '{split($2,a,"-");if(a[2]==01){b[$1]+=$4}}END{for(i in b)print i,b[i]}' test.txt
&二、substr 截取字符串
&&&&&&& 返回从起始位置起,指定长度之子字符串;若未指定长度,则返回从起始位置到字符串末尾的子字符串。格式:& substr(s,p) 返回字符串s中从p开始的后缀部分& substr(s,p,n) 返回字符串s中从p开始长度为n的后缀部分例子:
[root@test ~]# echo "123" | awk '{print substr($0,1,1)}'
awk -F ',' '{print substr($3,6)}'&&& ---&& 表示是从第3个字段里的第6个字符开始,一直到设定的分隔符","结束.substr($3,10,8)& ---&& 表示是从第3个字段里的第10个字符开始,截取8个字符结束.substr($3,6)&&&& ---&& 表示是从第3个字段里的第6个字符开始,一直到结尾三、length 字符串长度&& length函数返回没有参数的字符串的长度。length函数返回整个记录中的字符数。
[root@test ~]# echo "123" | awk '{print length}'
四、gsub函数
gsub函数则使得在所有正则表达式被匹配的时候都发生替换。gsub(regular expression, subsitution string, target string);简称 gsub(r,s,t)。
举例:把一个文件里面所有包含 abc 的行里面的 abc 替换成 def,然后输出第一列和第三列
awk '$0 ~ /abc/ {gsub("abc", "def", $0); print $1, $3}' abc.txt
五、正则表达式
指定如果一个或多个字符或扩展正则表达式的具体值(在&+(加号)前)在这个字符串中,则字符串匹配。命令行:
awk '/smith+ern/' testfile
将包含字符&smit,后跟一个或多个&h&字符,并以字符&ern&结束的字符串的任何记录打印至标准输出。此示例中的输出是:
smithern, harry smithhern, anne
指定如果零个或一个字符或扩展正则表达式的具体值(在 ?(问号)之前)在字符串中,则字符串匹配。命令行:
awk '/smith?/' testfile
将包含字符&smit,后跟零个或一个&h&字符的实例的所有记录打印至标准输出。此示例中的输出是:
smith, alan smithern, harry smithhern, anne smitters, alexis
指定如果以 |(垂直线)隔开的字符串的任何一个在字符串中,则字符串匹配。命令行:
awk '/allen | alan /' testfile
将包含字符串&allen&或&alan&的所有记录打印至标准输出。此示例中的输出是:
smiley, allen smith, alan
在正则表达式中将字符串组合在一起。命令行:
awk '/a(ll)?(nn)?e/' testfile
将具有字符串&ae&或&alle&或&anne&或&allnne&的所有记录打印至标准输出。此示例中的输出是:
smiley, allen smithhern, anne
指定如果正好有&m&个模式的具体值位于字符串中,则字符串匹配。命令行:
awk '/l{2}/' testfile
打印至标准输出
smiley, allen
指定如果至少&m&个模式的具体值在字符串中,则字符串匹配。命令行:
awk '/t{2,}/' testfile
打印至标准输出:
smitters, alexis
指定如果&m&和&n&之间(包含的 m 和 n)个模式的具体值在字符串中(其中m&=&n),则字符串匹配。命令行:
awk '/er{1, 2}/' testfile
打印至标准输出:
smithern, harry smithern, anne smitters, alexis
指定正则表达式与方括号内&String&变量指定的任何字符匹配。命令行:
awk '/sm[a-h]/' testfile
将具有&sm&后跟以字母顺序从&a&到&h&排列的任何字符的所有记录打印至标准输出。此示例的输出是:
smawley, andy
[^&String]
在 [ ](方括号)和在指定字符串开头的 ^ (插入记号) 指明正则表达式与方括号内的任何字符不匹配。这样,命令行:
awk '/sm[^a-h]/' testfile
打印至标准输出:
smiley, allen smith, alan smithern, harry smithhern, anne smitters, alexis
表示指定变量与正则表达式匹配(代字号)或不匹配(代字号、感叹号)的条件语句。命令行:
awk '$1 ~ /n/' testfile
将第一个字段包含字符&n&的所有记录打印至标准输出。此示例中的输出是:
smithern, harry smithhern, anne
指定字段或记录的开头。命令行:
awk '$2 ~ /^h/' testfile
将把字符&h&作为第二个字段的第一个字符的所有记录打印至标准输出。此示例中的输出是:
smithern, harry
指定字段或记录的末尾。命令行:
awk '$2 ~ /y$/' testfile
将把字符&y&作为第二个字段的最后一个字符的所有记录打印至标准输出。此示例中的输出是:
smawley, andy smithern, harry
.&(句号)
表示除了在空白末尾的终端换行字符以外的任何一个字符。命令行:
awk '/a..e/' testfile
将具有以两个字符隔开的字符&a&和 e 的所有记录打印至标准输出。此示例中的输出是:
smawley, andy smiley, allen smithhern, anne
表示零个或更多的任意字符。命令行:
awk '/a.*e/' testfile
将具有以零个或更多字符隔开的字符&a&和 e 的所有记录打印至标准输出。此示例中的输出是:
smawley, andy smiley, allen smithhern, anne smitters, alexis
\&(反斜杠)
转义字符。当位于在扩展正则表达式中具有特殊含义的任何字符之前时,转义字符除去该字符的任何特殊含义。例如,命令行:
将与模式 a // 匹配,因为反斜杠否定斜杠作为正则表达式定界符的通常含义。要将反斜杠本身指定为字符,则使用双反斜杠。有关反斜杠及其使用的更多信息,请参阅以下关于转义序列的内容。
举例:把一个文件里面所有包含 abc 的行里面的 abc 替换成 def,然后输出第一列和第三列
awk '$0 ~ /abc/ {gsub("abc", "def", $0); print $1, $3}' abc.txt
阅读(...) 评论()温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
R&D Dept., Sasmac, National Administration of Surveying, Mapping, and Geoinformation
Mobile: +86-
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(66363)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'Linux:使用awk命令获取文本的某一行,某一列',
blogAbstract:'1、打印文件的第一列(域)&&&&&&&&&&&& & & : awk \'{print $1}\' filename2、打印文件的前两列(域)&&&&&&&&&&&&&& & : awk \'{print $1,$2}\' filename3、打印完第一列,然后打印第二列& : awk \'{print $1 $2}\' filename4、打印文本文件的总行数&&&&&&&&&& & && : awk \'END{print NR}\' filename5、打印文本第一行&&&&&&&&&&&&&&&&&&&&&&&&& :awk \'NR==1{print}\' filename',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:2,
publishTime:2,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:1,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'Doctor\r\n\r\nR&D Dept., Sasmac, National Administration of Surveying, Mapping, and Geoinformation\r\n\r\nMobile: +86-\r\nEmail: , ',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}博客访问: 683550
博文数量: 193
博客积分: 1450
博客等级: 上尉
技术积分: 1982
注册时间:
嵌入人生,快乐前行。只是都学杂了,回过头来看,一切又都是相关的,这就是事物相关性吧。
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: 嵌入式
在linux中经常要对一些动态的文本文件抽取指定的字符串,比如执行ps命令后想要获取指定的运行进程(如ps自己)的PID号(同一个进程每次启动的时候pid号是随机分配的)。该怎么办呢?当然,可以用一些截取字符串的方法,这里介绍一下用2种方法来解决这类问题。
一、sed+grep方法:
首先大概了解一下sed,sed是linux里面一个非交互性的文本流编辑器(好长的定义,反正我听起来我很拗口)。解释2点:
1,非交互性:这里非交互性是指sed工具并不直接编辑目的文本文件,而是编辑目的文件的一个缓存拷贝,只能够修改拷贝文件,不会对源文件有任何的改动!也就是说编辑并不在目的文件现场!比如我想要编辑example.log文件,如果用必须直接打开example.log文件,然后在里面编辑。而sed是编辑example.log文件的一个拷贝,那么你可能要问了,这个拷贝在哪儿呢?这个拷贝在缓存里面,不需要我们自己拷贝,只要你调用了sed工具来编辑,系统自动会帮我们拷贝出一个example.log文件供你去编辑,从而保护不被随意改动。
2,文本流:文本流是指我们通过一定的shell指令对文本进行编辑,而不想vi编辑器一样需要把文件打开之后才能够进行编辑。比如我要删除example.log里面的第一行。vi里面必须先打开文件,然后选中第一行,再按下删除。如果你使用sed命令的话,就只要执行以下一行代码就可以干脆利落的删除掉第一行:sed '1d' example.log。现在可以知道,sed工具无需打开文件再进行操作,而是通过一系列命令操作文本流,所以叫做文本流编辑器。
好,现在来解决问题:
举个例子,比如使用的时候经常需要使用的一个命令是setkey -D来查看spi是否正常生成了。而每次ipsec连接的时候产生的spi是不一样的,当spi产生失误的时候,就会出现spi=;现在我想通过一定的shell脚本获取spi的值。setkey -D产生而定输出如下图
我们在说sed,当然使用sed来解决该问题。
明确一下我们的目的:我们的目的是要获取上图中的一段数据:spi=,并且每次如果ipsec重新启动的时候spi后面的数据会不一样(但长度一样,并且都是数字)。那么我们想到自然要用到正则表达式来匹配该段数据,然后输出到一个变量或者文件供我们后续使用。
再来看看sed给我们提供了什么方法:sed可以很方便的把某一行打印出来,sed -n '2p' example.log会打印出第二行。也就是说sed很容易获取行,这显然不能满足我们的需求。sed不会这么简单!sed还提供了删除,追加,插入,替换等丰富的方法来对一段文本进行编辑。
删除某一行:
追加:把hello,i was appended here 追加到有national这一行的的后面。
替换:sed 's/source string/destination string/' example.log
那么,我想既然sed可以非常方便的获取到某一行数据,而它又能够对文本进行编辑,那么,我的想法是,先用sed对文本进行一定的编辑,把目标字符串编辑到某一行内,我就非常方便的获取到了
好,照着这条思路走:
1,编辑文本,把目标字符串放到单独的一行里面来:观察之后可以看出,该段目的字符串spi=x0910327e)前后都有空格,那么就用空格作为重新编辑的标记位,前后换行。
输入命令:sed 's/ /\n/g' example.log。解释下命令,s是替换的标记,第一个/ /里面有一个空格,意思是查找所有含有空格的行,最后的g表明要对该行的所有空格进行查询,而不只是查询到第一个就查询下一行,第二个/\n/是一个换行符,结合前面的空格查询语法,可以对所有的空格替换成换行符。里面的命令执行后会把文本重新编排,遇到空格就换行,这样,目标字符串就已经到了单独的一行里面去了!!!
2,获取目标行字符串:现在就很简单了,我们可以用grep来获取(grep "spi" example.log),也可以用sed来获取(sed '/spi/p' example),把屏幕输出重定向到一个文件里面去,或者赋给一个变量,这样,我们抽取目标字符串的任务就完成了!!!
是不是很简单!!!好,下面来看awk方法
二、awk方法:
同样的,首先来大概了解一下awk方法的精髓,awk方法主要是对文本进行“列”的操作,这个对比一下sed和grep可能我们更容易理解一些,sed和grep主要是对文本进行“行”的操作,awk会把每一列都取一个名字,从第一列开始:分别为$1,$2...$n,好吧,这样就可以按照名字来分别操作列了。
好吧,现在我们来实例操作一下。
我们从ps输出里面去查询指定进程名字的PID,在我的终端直接输入ps x之后会显示当前进程的名字,其部分截图如下:
现在我想获取的是当前ps x输出里面的进程名为上图中红圈部分nautilus的PID值1355,由于相同进程会在不同的时候开启的时候所获取到的PID号不一样,所以当前的PID值1355其实是个不一定的数字。于是,我们只能通过进程名字nautilus来获取当前PID。好,目的明确之后进行操作:
1,配合使用管道,使用grep获取到包含nautilus的行:
发现有2个nautilus,好吧,那我们就来操作2个nautilus的PID,只是需要配合使用一下sed,没事,就当复习一下;
2,现在是awk派上用场的时候了:
继续使用管道,可以看到,利用命令可以得到进程名为nautilus的PID列:。
这里先来个小插曲,简单介绍一下awk命令的语法,awk基本语法为:awk [-F] "field-operator" 'comand' inputfiles,-F和field-operator一起使用,field-operator是域分隔符,如果不使用-F选项,则默认的域分隔符为空格。后面command命令一般需要用一堆“{}”括起来,然后进行必要的操作,比较全面一点的command命令'{if($1~/^A/) print $1}',翻译一下这个命令就是,如果第一列($1)里面有匹配(~)正则表达式(/^A/)的话,那么就输出(print)到标准输出。需要注意的是,条件必须要用一堆"()"括起来,正则表达式需要用“//”括起来。当然,完全可以不要条件匹配,可以直接输出指定列,如'{print $1}'。好,awk就介绍到这里,不过awk是一个非常非常强大的文本格式化抽取的工具,需要专门的学习。后面我再写一个关于awk学习的总结。
3,现在需要利用sed对"行"的操作了,我们获取到的第一行就是第一个nautilus的PID值,上面我们已经介绍了sed命令,所以很简单的,接着上面的管道,输入以下命令:
很快,我们就可以得到第一个nautilus的PID值了
是不是很简单,就简单的三部操作,grep——awk——sed,这三真是文本操作里面的拼命三郎啊
三、现在来稍微介绍一下cut方法
cut也是一个比较强大的工具,可以对一行字符串进行多种模式匹配的剪切操作,也可以对一个排列非常整齐的文本进行操作,下面通过2个例子来大致说明 一下cut的操作。
1,先说明cut对一行字符串的操作:
在终端执行echo $PATH命令,可以获得当前默认的bash路径,如下图:
其中每一个路径都被一个“:”分隔开来,现在我想获取第1个和第2个冒号之间的路径,使用cut将会非常之方便,在终端输入命令:
确实,我们获取到了第一个冒号与第二个冒号之间的字符串“/usr/local/bin”,现在来稍微解析一下这条命令,-d和':'一起把管道输入的一行字符串进行了域的分隔,每一个分隔符(在这里是个冒号“:”)前面的字符串被称为一个域,若有n个分隔符,这个域的编号则从1开始到n+1,第1个分隔符前面的字符串为第一个域。这个域对应在该命令行则是-f后面的数字2,所以该命令`cut -d ':' -f 2`表达的意思是输出第二个分隔符“:”之前的域。
如果我们执行
或者是cut -d ':' -f 2-4,则可以输出第2个和第四个域的字符串,但是还多了一个分隔符,这点我也没搞懂。
上面是是用分隔符对一行字符串进行操作,下面我们队字符串的每一个字母当成一个数组里面的元素,只是第一个元素是从1开始,而不是传统数组的0开始。这样可以进行另外一种cut操作,现在先定义一个字符串变量,并从中截取出1-5之间的字符:
可见,这条命令很好的把字符串“hello world”从第2个字母到第5个字母cut了下来,把最后的参数进行一下修改,如下:
则可以截取到第2个字符以及后面的所有的字符。
2,cut对格式化整齐的文本进行操作:
这是一段格式化比较整齐的数据,每一行前面的“declare -x”都是一模一样的,我现在想把这一段给去掉:
其实我们发现对该文本的操作跟上的一行字符串的操作没什么区别。
那么就验证一下对分隔符的操作是否也一样:
发现结果确实是一样。这说明cut会把一个文本里面的每一行都独立的对待,然后再操作。
阅读(1355) | 评论(0) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。十一.& awk编程:&&& 1.& 变量:&&&&在awk中变量无须定义即可使用,变量在赋值时即已经完成了定义。变量的类型可以是数字、字符串。根据使用的不同,未初始化变量的值为0或空白字符串" ",这主要取决于变量应用的上下文。下面为变量的赋值负号列表:
符号 含义 等价形式
= a = 5 a = 5
+= a = a + 5 a += 5
-= a = a - 5 a -= 5
*= a = a * 5 a *= 5
/= a = a / 5 a /= 5
%= a = a % 5 a %= 5
^= a = a ^ 5 a ^= 5
&&& /& awk '$1 ~ /Tom/ {Wage = $2 * $3; print Wage}' filename&& &该命令将从文件中读取,并查找第一个域字段匹配Tom的记录,再将其第二和第三个字段的乘积赋值给自定义的Wage变量,最后通过print命令将该变量打印输出。 &&& /& awk ' {$5 = 1000 * $3 / $2; print}' filename&& &在上面的命令中,如果$5不存在,awk将计算表达式1000 * $3 / $2的值,并将其赋值给$5。如果第五个域存在,则用表达式覆盖$5原来的值。&& &我们同样也可以在命令行中定义自定义的变量,用法如下:&&& /& awk -F: -f awkscript month=4 year=2011 filename&& &这里的month和year都是自定义变量,且分别被赋值为4和2000,在awk的脚本中这些变量将可以被直接使用,他们和脚本中定义的变量在使用上没有任何区别。&& &除此之外,awk还提供了一组内建变量(变量名全部大写),见如下列表:
变量名 变量内容
ARGC 命令行参数的数量。
ARGIND 命令行正在处理的当前文件的AGV的索引。
ARGV 命令行参数数组。
CONVFMT 转换数字格式。
ENVIRON 从shell中传递来的包含当前环境变量的数组。
ERRNO 当使用close函数或者通过getline函数读取的时候,发生的重新定向错误的描述信息就保存在这个变量中。
FIELDWIDTHS 在对记录进行固定域宽的分割时,可以替代FS的分隔符的列表。
FILENAME 当前的输入文件名。
FNR 当前文件的记录号。
FS 输入分隔符,默认是空格。
IGNORECASE 在正则表达式和字符串操作中关闭大小写敏感。
NF 当前文件域的数量。
NR 当前文件记录数。
OFMT 数字输出格式。
OFS 输出域分隔符。
ORS 输出记录分隔符。
RLENGTH 通过match函数匹配的字符串的长度。
RS 输入记录分隔符。
RSTART 通过match函数匹配的字符串的偏移量。
SUBSEP 下标分隔符。
&&& /& cat employees2&& &Tom Jones:/66:543354&& &Mary Adams:/63:28765&& &Sally Chang:/54:650000&& &Mary Black:/44:336500 &&& /& awk -F: '{IGNORECASE = 1}; $1 == "mary adams" { print NR, $1, $2, $NF}' employees2&& &2 Mary Adams
&&& /& awk -F: ' $1 == "mary adams" { print NR, $1, $2, $NF}' employees2&&& 没有输出结果。&&
&当IGNORECASE内置变量的值为非0时,表示在进行字符串操作和处理正则表达式时关闭大小写敏感。这里的"mary
adams"将匹配文件中的"Mary
Admams"记录。最后print打印出第一、第二和最后一个域。需要说明的是NF表示当前记录域的数量,因此$NF将表示最后一个域的值。&&
&awk在动作部分还提供了BEGIN块和END块。其中BEGIN动作块在awk处理任何输入文件行之前执行。事实上,BEGIN块可以在没有任何输入 文件的条件下测试。因为在BEGIN块执行完毕以前awk将不读取任何输入文件。BEGIN块通常被用来改变内建变量的值,如OFS、RS或FS等。也可 以用于初始化自定义变量值,或打印输出标题。 &&& /& awk 'BEGIN {FS = ":"; OFS = "\t"; ORS = "\n\n"} { print $1,$2,$3} filename&& &上例中awk在处理文件之前,已经将域分隔符(FS)设置为冒号,输出文件域分隔符(OFS)设置为制表符,输出记录分隔符(ORS)被设置为两个换行符。BEGIN之后的动作模块中如果有多个语句,他们之间用分号分隔。&& &和BEGIN恰恰相反,END模块中的动作是在整个文件处理完毕之后被执行的。 &&& /& awk 'END {print "The number of the records is " NR }' filename&& &awk在处理输入文件之后,执行END模块中的动作,上例中NR的值是读入的最后一个记录的记录号。&&& /& awk '/Mary/{count++} END{print "Mary was found " count " times." }' employees2&& &Mary was found 2 times. &&& /& awk '/Mary/{count++} END{print "Mary was found " count " times." }' employees2&& &Mary was found 2 times.&& &&& &/& cat testfile&& &northwest&&&&&& NW&&&&& Charles Main&&&&&&&&&&&&&&& 3.0&&&& .98&&&& 3&&&&&& 34&& &western&&&&&&&&& WE&&&&& Sharon Gray&&&&&&&&&&&&&&& 5.3&&&& .97&&&& 5&&&&&& 23&& &southwest&&&&&& SW&&&&& Lewis Dalsass&&&&&&&&&&&&& 2.7&&&& .8&&&&& 2&&&&&& 18&& &southern&&&&&&&& SO&&&&& Suan Chin&&&&&&&&&&&&&&&&&& 5.1&&&& .95&&&& 4&&&&&& 15&& &southeast&&&&&&& SE&&&&& Patricia Hemenway&&&&&&& 4.0&&&& .7&&&&& 4&&&&&& 17&& &eastern&&&&&&&&&& EA&&&&& TB Savage&&&&&&&&&&&&&&&&&& 4.4&&&& .84&&&& 5&&&&&& 20&& &northeast&&&&&&& NE&&&&& AM Main Jr.&&&&&&&&&&&&&&&&& 5.1&&&& .94&&&& 3&&&&&& 13&& &north&&&&&&&&&&&& NO&&&&&& Margot Weber&&&&&&&&&&&& 4.5&&&& .89&&&& 5&&&&&& 9&& &central&&&&&&&&&& CT&&&&&& Ann Stephens&&&&&&&&&&&&& 5.7&&&& .94&&&& 5&&&&&& 13&&& /& awk '/^north/{count += 1; print count}' testfile&& & #如记录以正则north开头,则创建变量count同时增一,再输出其值。&& &1&& &2&& &3&& &&& &#这里只是输出前三个字段,其中第七个域先被赋值给变量x,在自减一,最后再同时打印出他们。&& &/& awk 'NR &= 3 {x = $7--; print "x = " x ", $7 = " $7}' testfile&& &x = 3, $7 = 2&& &x = 5, $7 = 4&& &x = 2, $7 = 1&& &&& &&& &#打印NR(记录号)的值在2--5之间的记录。&& &/& awk 'NR == 2,NR == 5 {print "The record number is " NR}' testfile&& &The record number is 2&& &The record number is 3&& &The record number is 4&& &The record number is 5&& &#打印环境变量USER和HOME的值。环境变量的值由父进程shell传递给awk程序的。&& &/& awk 'BEGIN { print ENVIRON["USER"],ENVIRON["HOME"]}' && &root /root&& &&& &#BEGIN块儿中对OFS内置变量重新赋值了,因此后面的输出域分隔符改为了\t。&& &/& awk 'BEGIN { OFS = "\t"}; /^Sharon/{ print $1,$2,$7}' testfile&& &western WE&&&&& 5&& &&& &#从输入文件中找到以north开头的记录count就加一,最后在END块中输出该变量。&& &/& awk '/^north/{count++}; END{print count}' testfile&& &3 &&& 2.& 重新定向:&&&&在 动作语句中使用shell通用的重定向输出符号"&"就可以完成awk的重定向操作,当使用&的时候,原有文件将被清空,同时文件持续打开, 直到文件被明确的关闭或者awk程序终止。来自后面的打印语句的输出会追加到前面内容的后面。符号"&&"用来打开一个文件但是不清空原有文 件的内容,重定向的输出只是被追加到这个文件的末尾。&& &/& awk '$4 &= 70 {print $1,$2 & "passing_file"}' filename& #注意这里的文件名需要用双引号括起来。&&& #通过两次cat的结果可以看出&和&&的区别。&& &/& awk '/north/{print $1,$3,$4 & "districts" }' testfile&& &/& cat districts&& &northwest Joel Craig&& &northeast TJ Nichols&& &north Val Shultz&& &/& awk '/south/{print $1,$3,$4 && "districts" }' testfile&& &/& cat districts&& &northwest Joel Craig&& &northeast TJ Nichols&& &north Val Shultz&& &southwest Chris Foster&& &southern May Chin&& &southeast Derek Jonhson &&& &&
&awk中对于输入重定向是通过getline函数来完成的。getline函数的作用是从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得 输入。他负责从输入获得下一行的内容,并给NF、NR和FNR等内建变量赋值。如果得到一个记录,getline就返回1,如果达到文件末尾就返回0。如 果出现错误,如打开文件失败,就返回-1。&& &/& awk 'BEGIN { "date" | print d}'&& &Tue Nov 15 15:31:42 CST 2011&& &上例中的BEGIN动作模块中,先执行shell命令date,并通过管道输出给getline,然后再把输出赋值给自定义变量d并打印输出它。&& &&& &/& awk 'BEGIN { "date" | split(d,mon); print mon[2]}'&& &Nov&& &上例中date命令通过管道输出给getline并赋值给d变量,再通过内置函数split将d拆分为mon数组,最后print出mon数组的第二个元素。&& &&& &/& awk 'BEGIN { while("ls" | getline) print}'&& &employees&& &employees2&& &testfile&& &命令ls的输出传递给getline作为输入,循环的每个反复,getline都从ls的结果中读取一行输入,并把他打印到屏幕。&& &&& &/& 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? Mary&& &Found Mary on line& 2.&& &See ya, Mary.&& &&& &上例先是打印出BEGIN块中的"What is your name? ",然后等待用户从/dev/tty输入,并将读入的数据赋值给name变量,之后再从输入文件中读取记录,并找到匹配输入变量的记录并打印出来,最后在END块中输出结尾信息。&& &&&& /& awk 'BEGIN { while(getline & "/etc/passwd" & 0) lc++; print lc}'&& &32&& &awk将逐行读取/etc/passwd文件中的内容,在达到文件末尾之前,计数器lc一直自增1,当到了末尾后打印lc的值。lc的值为/etc/passwd文件的行数。&&& 由于awk中同时打开的管道只有一个,那么在打开下一个管道之前必须关闭它,管道符号右边可以通过可以通过双引号关闭管道。如果不关闭,它将始终保持打开状态,直到awk退出。&& &/& awk {print $1,$2,$3 | "sort -4 +1 -2 +0 -1"} END {close("sort -4 +1 -2 +0 -1") } filename&&& 上例中END模块中的close显示关闭了sort的管道,需要注意的是close中关闭的命令必须和当初打开时的完全匹配,否则END模块产生的输出会和以前的输出一起被sort分类。 &&& 3.& 条件语句:&&&&awk中的条件语句是从C语言中借鉴来的,见如下声明方式:&& &if (expression) {&& &&& &&& &&& &&& &&& &... ...&& &}& & /& awk '{if ($6 & 50) print $1 "Too hign"}' filename&& &/& awk '{if ($6 & 20 && $6 &= 50) { safe++; print "OK}}' filename&& &if (expression) {&& &&& &&& &} else {&& &&& &statement2;&& &}&& &/& awk '{if ($6 & 50) print $1 " Too high"; else print "Range is OK" }' filename&& &/& awk '{if ($6 & 50) { count++; print $3 } else { x = 5; print $5 }' filename&& &if (expression) {&& &&& &statement1;&& &} else if (expression1) {&& &&& &statement2;&& &} else {&& &&& &statement3;&& &}&& &/& awk '{if ($6 & 50) print "$6 & 50" else if ($6 & 30) print "$6 & 30" else print "other"}' filename&&&4.& 循环语句:&&&&awk中的循环语句同样借鉴于C语言,支持while、do/while、for、break、continue,这些关键字的语义和C语言中的语义完全相同。&&&&5.& 流程控制语句:&&&&next语句是从文件中读取下一行,然后从头开始执行awk脚本。&& &exit语句用于结束awk程序。它终止对记录的处理。但是不会略过END模块,如果exit()语句被赋值0--255之间的参数,如exit(1),这个参数就被打印到命令行,以判断退出成功还是失败。&&&&6.& 数组:&&&&因 为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格 里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也 同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。&& &/& cat employees&& &Tom Jones&&&&&& 4424&&& 5/12/66&&&&&&&& 543354&& &Mary Adams&&&&& 5346&&& 11/4/63&&&&&&&& 28765&& &Sally Chang&&&& 1654&&& 7/22/54&&&&&&&& 650000&& &Billy Black&&&& 1683&&& 9/23/44&&&&&&&& 336500&& &/& awk '{name[x++] = $2}; END{for (i = 0; i & NR; i++) print i, name[i]}' employees&& &&& &0 Jones&& &1 Adams&& &2 Chang&& &3 Black&& &在上例中,数组name的下标是变量x。awk初始化该变量的值为0,在每次使用后自增1,读取文件中的第二个域的值被依次赋值给name数组的各个元素。在END模块中,for循环遍历数组的值。因为下标是关键字,所以它不一定从0开始,可以从任何值开始。&& &#这里是用内置变量NR作为数组的下标了。&& &/& awk '{id[NR] = $3}; END {for (x = 1; x &= NR; x++) print id[x]}' employees&& &4424&& &5346&& &1654&& &1683&& &awk中还提供了一种special for的循环,见如下声明:&& &for (item in arrayname) {&& &&& &print arrayname[item]&& &}&& &/& cat db&& &Tom Jones&& &Mary Adams&& &Sally Chang&& &Billy Black&& &Tom Savage&& &Tom Chung&& &Reggie Steel&& &Tommy Tucker&& &/& awk '/^Tom/{name[NR]=$1}; END {for(i = 1;i &= NR; i++) print name[i]}' db&& &Tom&& &Tom&& &Tom&& &Tommy&&
&从输出结果可以看出,只有匹配正则表达式的记录的第一个域被赋值给数组name的指定下标元素。因为用NR作为下标,所以数组的下标不可能是连续的,因 此在END模块中用传统的for循环打印时,不存在的元素就打印空字符串了。下面我们看看用special for的方式会有什么样的输出。&& &/& awk '/^Tom/{name[NR]=$1};END{for(i in name) print name[i]}' db&& &Tom&& &Tom&& &Tommy&& &Tom&& &下面我们看一下用字符串作为下标的例子:(如果下标是字符串文字常量,则需要用双引号括起来)&& &&& &/& cat testfile2&& &tom&& &mary&& &sean&& &tom&& &mary&& &mary&& &bob&& &mary&& &alex& & /& awk '/tom/{count["tom"]++}; /mary/{count["mary"]++}; END{print "There are " count["tom"] \&& &&& &" Toms and " count["mary"] " Marys in the file."} testfile2&& &There are 2 Toms and 4 Marys in the file.&& &在上例中,count数组有两个元素,下标分别为tom和mary,每一个元素的初始值都是0,没有tom被匹配的时候,count["tom"]就会加一,count["mary"]在匹配mary的时候也同样如此。END模块中打印出存储在数组中的各个元素。&& &/& awk '{count[$1]++}; END{for(name in count) printf "%-5s%d\n",name, count[name]}' testfile2&& &mary 4&& &tom& 2&& &alex 1&& &bob& 1&& &sean 1&& &在上例中,awk是以记录的域作为数组count的下标。&&
&/& awk '{count[$1]++; if (count[$1] & 1) name[$1]++}; END{print
"The duplicates were "; for(i in name) print i}' testfile2&& &The duplicates were&& &mary&& &tom&& &在上例中,如count[$1]的元素值大于1的时候,也就是当名字出现多次的时候,一个新的数组name将被初始化,最后打印出那么数组中重复出现的名字下标。&& &之前我们介绍的都是如何给数组添加新的元素,并赋予初值,现在我们需要介绍一下如何删除数组中已经存在的元素。要完成这一功能我们需要使用内置函数delete,见如下命令:&& &/& awk '{count[$1]++}; \&& &&& &END{for(name in count) {\&& &&&&&&&&&&&& if (count[name] == 1)\&& &&&&&&&&&&&&&&&& delete count[name];\&& &&&&&&&& } \&& &&&&&&&& for (name in count) \&& &&&&&&&&&&&& print name}' testfile2&& &mary&& &tom&& &上例中的主要技巧来自END模块,先是变量count数组,如果数组中某个元素的值等于1,则删除该元素,这样等同于删除只出现一次的名字。最后用special for循环打印出数组中仍然存在的元素下标名称。&& &最后我们来看一下如何使用命令行参数数组,见如下命令:&&
&/& awk 'BEGIN {for(i = 0; i & ARGC; i++) printf("argv[%d] is
%s.\n",i,ARGV[i]); printf("The number of arguments, ARGC=%d\n",ARGC)}'
testfile "Peter Pan" 12&& &argv[0] is awk.&& &argv[1] is testfile.&& &argv[2] is Peter Pan.&& &argv[3] is 12.&& &The number of arguments, ARGC=4&& &从输出结果可以看出,命令行参数数组ARGV是以0作为起始下标的,命令行的第一个参数为命令本身(awk),这个使用方式和C语句main函数完全一致。&& &/& awk 'BEGIN{name=ARGV[2]; print "ARGV[2] is " ARGV[2]}; $1 ~ name{print $0}' testfile2 "bob"&& &&& &ARGV[2] is bob&& &bob&& &awk: (FILENAME=testfile2 FNR=9) fatal: cannot open file `bob' for reading (No such file or directory)&& &先解释一下以上命令的含义,name变量被赋值为命令行的第三个参数,即bob,之后再在输入文件中找到匹配该变量值的记录,并打印出该记录。&& &在输出的第二行报出了awk的处理错误信息,这主要是因为awk将bob视为输入文件来处理了,然而事实上这个文件并不存在,下面我们需要做进一步的处理来修正这个问题。&& &/& awk 'BEGIN{name=ARGV[2]; print "ARGV[2] is " ARGV[2]; delete ARGV[2]}; $1 ~ name{print $0}' testfile2 "bob"&& &&& &ARGV[2] is bob&& &bob&& &从输出结果中我们可以看到我们得到了我们想要的结果。需要注意的是delete函数的调用必要要在BEGIN模块中完成,因为这时awk还没有开始读取命令行参数中指定的文件。&&&&7.& 内建函数:&&&&字符串函数&& &sub(regular expression,substitution string);&& &sub(regular expression,substitution string,target string);&& &/& awk '{sub("Tom","Tommy"); print}' employees&& #这里使用Tommy替换了Tom。&& &Tommy Jones&&&&&& 4424&&& 5/12/66&&&&&&&& 543354&& &#当正则表达式Tom在第一个域中第一次被匹配后,他将被字符串"Tommy"替换,如果将sub函数的第三个参数改为$2,将不会有替换发生。&& &/& awk '{sub("Tom","Tommy",$1); print}' employees&& &Tommy Jones&&&&&& 4424&&& 5/12/66&&&&&&&& 543354&& &gsub(regular expression,substitution string);&& &gsub(regular expression,substitution string,target string);&& &和sub不同的是,如果第一个参数中正则表达式在记录中出现多次,那么gsub将完成多次替换,而sub只是替换第一次出现的。&& &index(string,substring)&& &该函数将返回第二个参数在第一个参数中出现的位置,偏移量从1开始。&& &/& awk 'BEGIN{print index("hello","el")}'&& &2&& &length(string)&& &该函数返回字符串的长度。&& &/& awk 'BEGIN{print length("hello")}'&& &5&& &substr(string,starting position)&& &substr(string,starting position,length of string)&& &该函数返回第一个参数的子字符串,其截取起始位置为第二个参数(偏移量为1),截取长度为第三个参数,如果没有该参数,则从第二个参数指定的位置起,直到string的末尾。&& &/&& awk 'BEGIN{name = substr("Hello World",2,3); print name}'&& &ell& & match(string,regular expression)&& &该函数返回在字符串中正则表达式位置的索引,如果找不到指定的正则表达式就返回0.match函数设置内置变量RSTART为字符串中子字符串的开始位置,RLENGTH为到字字符串末尾的字符个数。&& &/& awk 'BEGIN{start=match("Good ole CHINA", /[A-Z]+$/); print start}'&& &10&& &上例中的正则表达式[A-Z]+$表示在字符串的末尾搜索连续的大写字母。在字符串"Good ole CHINA"的第10个位置找到字符串"CHINA"。& & /& awk 'BEGIN{start=match("Good ole CHINA", /[A-Z]+$/); print RSTART, RLENGTH}'&& &10 5&& &RSTART表示匹配时的起始索引,RLENGTH表示匹配的长度。&& &/& awk 'BEGIN{string="Good ole CHINA";start=match(string, /[A-Z]+$/); print substr(string,RSTART, RLENGTH)}'&& &CHINA&& &这里将match、RSTART、RLENGTH和substr巧妙的结合起来了。&& &toupper(string)&& &tolower(string)&& &以上两个函数分别返回参数字符串的大写和小写的形式。&& &/& awk 'BEGIN {print toupper("hello"); print tolower("WORLD")}'&& &HELLO&& &world&& &split(string,array,field seperator)&& &split(string,array)&& &该函数使用作为第三个参数的域分隔符把字符串分隔为一个数组。如果第三个参数没有提供,则使用当前默认的FS值。&& &/& awk 'BEGIN{split("11/20/2011",date,"/"); print date[2]}'&& &20&& &variable = sprintf("string with format specifiers ",expr1,expr2,...)&& &该函数和printf的差别等同于C语言中printf和sprintf的差别。前者将格式化后的结果输出到输出流,而后者输出到函数的返回值中。&& &/& awk 'BEGIN{line = sprintf("%-15s %6.2f ", "hello",4.2); print line}'&& &hello&&&&&&&&&&&& 4.20&& &时间函数:&& &systime()&& &该函数返回当前时间距离日之间相差的秒数。&& &/& awk 'BEGIN{print systime()}'&& &&& &strftime()&& &时间格式化函数,其格式化规则等同于C语言中的strftime函数提供的规则,见以下列表:
数据格式 含义
%a Abbreviated weekday name
%A Full weekday name
%b Abbreviated month name
%B Full month name
%c Date and time representation appropriate for locale
%d Day of month as decimal number (01 – 31)
%H Hour in 24-hour format (00 – 23)
%I Hour in 12-hour format (01 – 12)
%j Day of year as decimal number (001 &#)
%m Month as decimal number (01 – 12)
%M Minute as decimal number (00 – 59)
%p Current locale's A.M./P.M. indicator for 12-hour clock
%S Second as decimal number (00 – 59)
%U Week of year as decimal number, with Sunday as first day of week (00 – 53)
%w Weekday as decimal number (0 – 6; Sunday is 0)
%W Week of year as decimal number, with Monday as first day of week (00 – 53)
%x Date representation for current locale
%X Time representation for current locale
%y Year without century, as decimal number (00 – 99)
%Y Year with century, as decimal number
&&& /& awk 'BEGIN{ print strftime("%D",systime())}'&& &11/15/11&& &/& awk 'BEGIN{ now = strftime("%T"); print now}'&& &23:17:29&& &内置数学函数:
名称 返回值
atan2(x,y) y,x范围内的余切
cos(x) 余弦函数
exp(x) 求幂
int(x) 取整
log(x) 自然对数
sin(x) 正弦函数
sqrt(x) 平方根
&&& /& awk 'BEGIN{print 31/3}'&& &10.3333&& &/& awk 'BEGIN{print int(31/3)}'&& &10&& &自定义函数:&& &自定义函数可以放在awk脚本的任何可以放置模板和动作的地方。&& &function name(parameter1,parameter2,...) {&& &&& &statements&& &&& &return expression&& &}&&
&给函数中本地变量传递值。只使用变量的拷贝。数组通过地址或者指针传递,所以可以在函数内部直接改变数组元素的值。函数内部使用的任何没有作为参数传递 的变量都被看做是全局变量,也就是这些变量对于整个程序都是可见的。如果变量在函数中发生了变化,那么就是在整个程序中发生了改变。唯一向函数提供本地变 量的办法就是把他们放在参数列表中,这些参数通常被放在列表的最后。如果函数调用没有提供正式的参数,那么参数就初始化为空。return语句通常就返回 程序控制并向调用者返回一个值。&& &/& cat grades&& &20 10&& &30 20&& &40 30&& &/& cat add.sc&& &function add(first,second) {&& &&&&&&&& return first + second&& &}&& &{ print add($1,$2) }&& &/& awk -f add.sc grades&& &30&& &50&& &70&&转载自,仅做学习收藏用途。 &
阅读(...) 评论()

我要回帖

更多关于 awk print 双引号 的文章

 

随机推荐