网上一道题,让我今晚睡不着了……
题目是这样的有一个文件file.log内容如下
[root@Jason64-17~]# cat net01.txt.bak
912012091210203212 3487923(feixue11) 1500(3600) 15 2012-09-01 12:23:12
912012091010303456 8434662(woshini) 1000(2000) 10 2012-09-04 02:12:34
912012090910501233 7856091(sda3sd) 200(1200) 2 2012-09-07 12:11:46
912012090510604567 5621697(dsa4fg) 500(600) 5 2012-09-04 12:39:32
需求是要把括号里面的内容取出来放在一个指定的文件goal.txt
好,我承认我看到这个题以后我体内的荷尔蒙分泌过多了;但是我就喜欢数据处理!
立马脑子里蹦出来awk对我说,大哥用我吧,我很简单就能搞定它。我手一伸,在键盘上敲下
[root@Jason64-17~]# awk -F '[()]' '{print $2,$4}' file.logfeixue11 3600woshini 2000sda3sd 1200dsa4fg 600[root@Jason64-17~]# awk -F '[()]' '{print $2,$4}' file.log >goal.txt[root@Jason64-17~]# cat goal.txtfeixue11 3600woshini 2000sda3sd 1200dsa4fg 600[root@Jason64-17~]# nl goal.txt 1 feixue11 3600 2 woshini 2000 3 sda3sd 1200 4 dsa4fg 600
Bingo!搞定了。看了其他的网友的答案,感觉自己是挺简单的。
然后就尝试用其他的办法解决。awk还有一个办法能解决
利用全局函数,将”(”和”)”都替换为空格“ ”,也可以达到目的。
[root@Jason64-17~]# awk '{gsub(/[()]/," ");print $3,$5}' file.logfeixue11 3600woshini 2000sda3sd 1200dsa4fg 600
来个笨办法
[root@Jason64-17~]# cat file.log912012091210203212 3487923(feixue11) 1500(3600) 15 2012-09-01 12:23:12912012091010303456 8434662(woshini) 1000(2000) 10 2012-09-04 02:12:34912012090910501233 7856091(sda3sd) 200(1200) 2 2012-09-07 12:11:46912012090510604567 5621697(dsa4fg) 500(600) 5 2012-09-04 12:39:32[root@Jason64-17~]# awk '{gsub(/[0-9]+\(/,"");print}' file.log912012091210203212 feixue11) 3600) 15 2012-09-01 12:23:12912012091010303456 woshini) 2000) 10 2012-09-04 02:12:34912012090910501233 sda3sd) 1200) 2 2012-09-07 12:11:46912012090510604567 dsa4fg) 600) 5 2012-09-04 12:39:32[root@Jason64-17~]# awk '{gsub(/[0-9]+\(/,"");gsub(/\)\W/, "");print}'file.log912012091210203212 feixue11 3600 15 2012-09-01 12:23:12912012091010303456 woshini 2000 10 2012-09-04 02:12:34912012090910501233 sda3sd 1200 2 2012-09-07 12:11:46912012090510604567 dsa4fg 600 5 2012-09-04 12:39:32[root@Jason64-17~]# awk '{gsub(/[0-9]+\(/,"");gsub(/\)\W/, "");print$2,$3}' file.logfeixue11 3600woshini 2000sda3sd 1200dsa4fg 600
再来个更笨的;是awk的sub函数,用了三个才把该去掉的去掉。
[root@Jason64-17~]# cat file.log912012091210203212 3487923(feixue11) 1500(3600) 15 2012-09-01 12:23:12912012091010303456 8434662(woshini) 1000(2000) 10 2012-09-04 02:12:34912012090910501233 7856091(sda3sd) 200(1200) 2 2012-09-07 12:11:46912012090510604567 5621697(dsa4fg) 500(600) 5 2012-09-04 12:39:32[root@Jason64-17~]# awk '{sub(/.*\(/,"",$2);print}' file.log912012091210203212 feixue11) 1500(3600) 152012-09-01 12:23:12912012091010303456 woshini) 1000(2000) 10 2012-09-0402:12:34912012090910501233 sda3sd) 200(1200) 2 2012-09-0712:11:46912012090510604567 dsa4fg) 500(600) 5 2012-09-0412:39:32 [root@Jason64-17 ~]# awk'{sub(/.*\(/,"",$2);sub(/\).*\(/, " ");print}' file.log912012091210203212 feixue11 3600) 15 2012-09-0112:23:12912012091010303456 woshini 2000) 10 2012-09-0402:12:34912012090910501233 sda3sd 1200) 2 2012-09-0712:11:46912012090510604567 dsa4fg 600) 5 2012-09-0412:39:32[root@Jason64-17~]# awk '{sub(/.*\(/,"",$2);sub(/\).*\(/, "");sub(/\).*/,"");print}' file.log912012091210203212 feixue11 3600912012091010303456 woshini 2000912012090910501233 sda3sd 1200912012090510604567 dsa4fg 600[root@Jason64-17~]# awk '{sub(/.*\(/,"",$2);sub(/\).*\(/, "");sub(/\).*/,"");print $2,$3}' file.logfeixue11 3600woshini 2000sda3sd 1200dsa4fg 600
注意,在awk里()是有特殊意义的,需要转义才可以。
下面用sed解。
sed的用法也很多,我简单的介绍几种。
[root@Jason64-17 ~]# cat file.log912012091210203212 3487923(feixue11) 1500(3600) 15 2012-09-01 12:23:12912012091010303456 8434662(woshini) 1000(2000) 10 2012-09-04 02:12:34912012090910501233 7856091(sda3sd) 200(1200) 2 2012-09-07 12:11:46912012090510604567 5621697(dsa4fg) 500(600) 5 2012-09-04 12:39:32[root@Jason64-17 ~]# sed 's#[()]# #g' file.log912012091210203212 3487923 feixue11 1500 3600 15 2012-09-01 12:23:12912012091010303456 8434662 woshini 1000 2000 10 2012-09-04 02:12:34912012090910501233 7856091 sda3sd 200 1200 2 2012-09-07 12:11:46912012090510604567 5621697 dsa4fg 500 600 5 2012-09-04 12:39:32[root@Jason64-17 ~]# sed 's#[()]# #g' file.log|awk '{print $3,$5}'feixue11 3600woshini 2000sda3sd 1200dsa4fg 600
这个是有点像那个awk的gsub的函数。
然后还可以直接匹配进行筛选
[root@Jason64-17~]# sed 's#[^(]*(\(.*\))\W.*(\(.*\)).*#\1 \2#' file.logfeixue11 3600woshini 2000sda3sd 1200dsa4fg 600
很多人对这行代码不是很清楚。我来解释下
[^(] 表示的是非(的字符
[^(]* 表示0到任意个非(的任意字符
-
[^(]*( 就表示匹配到第一个(
【PS:闹了半天就是为了证明匹配到的一定是第一个(】
\(.*\) 就是为了保存我们要的东西,标签标记为\1;如果有多个可以标记为\2。一个标签最多能够被引用9次。
)\W.*( 就匹配的是一个)后面接一个特殊字符(空格,回车等),然后再接任意字符再接一个(
\(.*\) 保留我们需要的第二个标签内容
).* 表示再接一个),后面接任意字符
这样就将一整行用正则匹配下来了。然后标签标记我们想要的内容,在后面引用就ok了。
在这里要提醒大家,awk是支持基础的正则表达式和扩展式的正则表达式;而sed只是支持基础的,并不支持扩展式正则表达式。如果想sed支持扩展式那么就要加-r参数。
当然,上述题还可以用扩展式的sed写出来,仅供参考
[root@Jason64-17~]# sed -r 's#[^(]*\((.*)\)\W.*\((.*)\).*#\1 \2#' file.log feixue11 3600woshini 2000sda3sd 1200dsa4fg 600
以上内容仅供参考!
说给博友的话:方法很多,还请大家发动大脑,多思考下看还有没有更好的办法!有想法和建议的可以留言。谢谢!
本文出自 “Lisp的运维之路” 博客,请务必保留此出处http://lspgyy.blog.51cto.com/5264172/1305290