马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
之前我做一些基本的文本处理也都是喜欢用perl来写脚本实现。这样做还是比较麻烦,效率也不高,其实可以使用SED和AWK的一些基本(组合)命令来实现。 SED和AWK也可以支持脚本,不过如果要写脚本的话,我倒更愿意去写Perl的脚本了。所以下面的例子基本都是一行命令的处理例子。 -------------- SED--------------- 例子1: 给每一行后面都加一行“000”的行---》比如,NE的testpattern全是y的,需要给它加上uv分量。 sed -e 'a\\ ? 000' t.txt 注意:上面是2行,必须用换行符,否则就得用sed脚本-f了 如果是每2行增加2行00: sed -e 'n;a\\ ?00\n00' tt.txt 例子2: 删除奇数行(只要偶数行) sed -n -e 'n;p' t.txt 分析: -n是不打印,如果不加-n,会导致偶数航被打印2次。 'n;p'的意思是下一行打印。用这个方式来剔除了奇数行 例子3: 删除偶数行(只要奇数行) sed -e 'n;d' t.txt 分析: 用d直接把偶数行删除了 例子4: 只打印指定字符串"lisj"的行(类似于grep) sed -e '/lisj/p' -n t.txt 例子5: 删除第一行 sed -e '1d' t.txt 删除第1到第4行 sed -e '1,4d' t.txt 删除第1行到第一个包含指定字符串“study”的行 sed -e '1,/study/d' t.txt 删除第一个包含指定字符串“compiler”到第一个指定字符串“study”的行 sed -e '/compile/,/study/d' t.txt 例子6: 为每一行前面加上“[ ]” sed 's/^/[ ]/g' t.txt 为每一行后面加上"[ ]" sed 's/$/[ ]/g' t.txt 例子7: 显示匹配行的行号 sed '/sed/=' t.txt sed '/sed/=' -n t.txt 注意:如果不加-n选项,则会打印整个文件和匹配行的行号。加了-n就会只打印匹配行的行号 sed -n -e '/sed/=' -e '/sed/p' t.txt 分析: 这样就会打印匹配行的行号和匹配航的内容 sed -n -e '/sed/p' -e '/sed/=' t.txt 分析: 只是与上面命令的显示顺序不一样 例子8: 限定范围以后的模式匹配和替换。 把所有包含指定字符串“sed”的行里的第一个e改成“EE” sed '/sed/s/e/EE/' t.txt 例子9: &用法,获取前面匹配的内容 把“sed”,换成“sed ABC” sed 's/sed/& ABC/' t.txt 把所有含“sed”的行用()括起来 sed '/sed/s/.*/(&)/' t.txt 例子10: \1用法,类似于perl的匹配时候的$1 把每行里第一个“li”替换成“li+gyl” sed 's/\(li\)/\1+gyl/' t.txt 注意: \(li\) 例子11:只打印1到4行里包含“sed”的行 sed -n -e '1,4p' t.txt | sed -n -e '/sed/p' 例子12:!用法 只保留文件的1到4行 sed -e '1,4\!d' t.txt 注意: 我发现得用\!来转义,但是书上看到的例子却没有用转义 -----------------AWK---------- 假设t.txt内容是: name birthday age gender begin_working lishujie 1980/10/17 32 Male 24 gongyanli 1981/10/20 31 Female 26 liyuxuan 2008/09/21 4 Female 4 例子:把一个文件的第一行去掉,然后选取每行的第一个域和第四个域,并且在文件一开始增加内容,文件末尾增加内容 sed '1d' t.txt | awk 'BEGIN {print "Name gender \n----------------"}{print $1,$4} END {print"End-of-print"}' 注意:AWK默认以空格来区分域。如果不是空格的话需要用 -F seperate-operator来指定。 AWK里的正则匹配~ 不匹配!~ 例子:把匹配某字符串的行打印出来 awk '{if($4~/Female/) print $0}' t.txt 注意:$0是指的把正行都打印出来。if实现精确的匹配,也可以不用if。比如上述命令简化为 awk '$0 ~ /Female/' t.txt 再比如: awk '$3 == 31' t.txt awk '/^li/' t.txt awk '{if($3 == 31 && $1=="gongyanli") print $0}' t.txt awk '{if($3 == 31 || $1=="lishujie") print $0}' t.txt AWK里的内置变量。内置变量比较多,建议看参考书。举几个例子: FILENAME awk浏览的文件名 FNR 浏览文件的记录数 FS 设置输入域分隔符,等价于命令行- F选项 NF 浏览记录的域个数 NR 已读的记录数 例子:获取文件行数 awk 'END{print NR}' t.txt 例子:在每行前面加上 域个数、行号;在最后加上文件名信息 awk '{print NF,NR,$0} END {print FILENAME}' t.txt 例子:从PWD中抽取文件夹名 echo `pwd` | awk -F / '{print $NF}' 给域设置域变量名,方便使用 awk '{name=$1;age=$3;if(name=="lishujie") print name "'\''s age is "age}' t.txt 注意:这里牵扯到了如何在AWK里打印单引号的问题。 解决方法是 把转义的单引号 ‘ 用两个单引号括起来并且加上转义符号,使其不执行 设置局部的变量: awk '{name=$1;age=$3;max_age=31 ;if($3<max_age) print name "'\''s age is "age}' t.txt 在awk里实现运算: awk '{name=$1;age=$3 ;age=age+1; if (name !~ /name/) print "Next year "name "'\''s age is "age}' t.txt 修改域值: awk '{if ($1 ~ /lishujie/) $1 = "dad" ; if ($1 ~ /gongyanli/) $1 = "mum" ;print $0}' t.txt 这个还是会把所有的记录都打印出来,如果想只打印修改的记录怎么处理呢? awk '{if ($1 ~ /gongyanli/) {$1 = "mum" ;print $0}}' t.txt 注意: 使用大括号来设置命令的执行范围就可以了。 增加一列参数“working_year” 并且计算数值。 第一行表头处理方法: awk '{if (NR == 1) printf "%s\t working_year\n",$0}' t.txt 注意:这里用printf来实现去掉$0里的换行符。 后面数据处理方法: awk '{if (NR > 1) {working_year = $3-$5;printf "%s\t%d \n",$0,working_year}}' t.txt 把上述两个命令合并在一起就可以了 awk '{if (NR == 1) printf "%s\t working_year\n",$0} {if (NR > 1) {working_year = $3-$5;printf "%s\t%d \n",$0,working_year}}' t.txt 统计列值的累加值: awk '{tot+=$3;print $0}END{print "tot age is "tot}' t.txt 不打印文件内容,只统计列值的话,就不要“print $0” awk '{tot+=$3}END{print "my family total age is "tot}' t.txt |