sed和awk

今天处理个输出结果,为了懒得重新写一个perl脚本,直接敲awk命令输出,敲了老半天都没敲对,着实汗了会

sed

一般用来文本处理,信息替换,内容切割,当然假如你不指定哪行或者哪些行,sed会默认整个文件全文处理

因为它本身就是一个管道命令,通常默认会将结果信息输出在屏幕上,实际上它在处理过程中会将处理的行保存在一个临时缓冲区中,也叫pattern space模式空间,然后处理该行,完成后输出到屏幕,处理一行就从缓冲区里删掉,然后将下一行读入,处理,显示,直到处理完文件的最后一行,sed便宣告结束,也就是说,sed处理的实际上一直都是文件的副本,根本就没有对原输入文件干啥子,所以就不会改

sed的一些选项,什么-n/-f/-r等,直接上网搜一大把,就不多写了,但是唯独有一个选项输出的结果与上面一段的内容不符,那就是-i

比如有这么有一个需求,要求将一个文件名为input_file里所有的hello替换成hi,这里不考虑单独词汇还是一个字符串中包含的区分关系,全局替换,用perl很容易几行实现:

#!/usr/bin/perl

$^I=”;
while(<>){
    s/hello/hi/g;
    print;
}

然后perl XXX.pl input_file就搞定,其中s/hello/hi/g;这行很容易看明白就是全局替换,代码的功能的确是将input_file里的hello全部替换成了hi,可是,第一行的$^I=”;是干啥的呢?感觉有点多余,其实这一句才是决定这个脚本是如何文件处理的关键,假如把这行改成$^I=’.bak’;运行一下立马就明白了,因为会产生一个中间文件input_file.bak,内容就是处理前的文件内容,也就是说将原文件备份了一下.bak,然后input_file变成了处理后的内容,而$^I=”;则把这个过程给掩盖了,因为备份文件最终被同名的处理后的文件覆盖了

上面这个例子是为了说下我平时用的最多的一个sed选项-i,假如你执行下面命令:

sed –i ‘s/hello/hi/g’ input_file

立马会发现,跟上面perl脚本达到了同样的效果,可是应该如何理解呢,有了上面perl这段经验,其实sed的-i选项的结果的确是原文件进行修改,过程可以这么理解:

sed ‘s/hello/hi/g’ input_file > input_file.bak

mv input_file.bak input_file

最终说到底,-i选项就是直接修改读取的文件内容,而不是通过屏幕输出

 

awk

用到awk主要是处理列相当给力,不然还要写个几行perl脚本,说不定还要通过正则表达式匹配特定列内容,都说perl程序员滥用正则表达式是perl被人鄙视的原因之一,我感觉自己也做了一份贡献

awk ‘{print $1}’ input_file

就这么一句,就把input_file的第一列(每行第一个空格前面的内容)给输出来了,特别对于处理那种输出内容每行格式相对工整,固定的来说太合适了,当然了大部分还是流行perl或者python里的split赋给列表,但是假如做命令行的测试输出,awk用起来还是非常的舒适,特别还可以结合shell的不停管道符号,然后难看了点,但是给人的感觉还是挺高大上的,随便找了两句以前写的,然后看个两眼还不清楚到底啥意思:

awk ‘BEGIN{sum=0}{sum+=$1}END{print sum}’ ${status_code:1:3}.txt | sed ‘s/,//g’ | sed ‘/^$/d’ >> ${status_code:1:3}.request.txt

awk ‘{a[$2]+=$3;} END {for(i in a) {if(a[i]>0) {print i”\t\t”a[i];}}}’ $status’.txt’ | sort

awk应该是一个非常强大的东西,用好它的确感觉是比较牛逼的人干的事,同样感觉shell能用得很熟练的人,应该都是比较内涵次的人,是咋们只可远观而不可亵玩焉的~!

发表回复