数据处理---三剑客中awk和sed

时间:2021-06-20 16:03:38

网上一道题,让我今晚睡不着了……

题目是这样的有一个文件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

再来个更笨的;是awksub函数,用了三个才把该去掉的去掉。

[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

这个是有点像那个awkgsub的函数。

然后还可以直接匹配进行筛选

[root@Jason64-17~]# sed 's#[^(]*(\(.*\))\W.*(\(.*\)).*#\1 \2#' file.logfeixue11 3600woshini 2000sda3sd 1200dsa4fg 600

很多人对这行代码不是很清楚。我来解释下

  1. [^(] 表示的是非(的字符

  2. [^(]* 表示0到任意个非(的任意字符

  3. [^(]*( 就表示匹配到第一个(

    PS:闹了半天就是为了证明匹配到的一定是第一个(

  4. \(.*\) 就是为了保存我们要的东西,标签标记为\1;如果有多个可以标记为\2。一个标签最多能够被引用9次。

  5. )\W.*( 就匹配的是一个)后面接一个特殊字符(空格,回车等),然后再接任意字符再接一个(

  6. \(.*\) 保留我们需要的第二个标签内容

  7. ).* 表示再接一个),后面接任意字符

这样就将一整行用正则匹配下来了。然后标签标记我们想要的内容,在后面引用就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