數據處理---三劍客中awk和sed

網上一道題,讓我今晚睡不着了……

題目是這樣的有一個文件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.log
feixue11 3600
woshini 2000
sda3sd 1200
dsa4fg 600
[root@Jason64-17~]# awk -F '[()]' '{print $2,$4}' file.log >goal.txt
[root@Jason64-17~]# cat goal.txt
feixue11 3600
woshini 2000
sda3sd 1200
dsa4fg 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.log
feixue11 3600
woshini 2000
sda3sd 1200
dsa4fg 600

來個笨辦法

[root@Jason64-17~]# cat file.log
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
[root@Jason64-17~]# awk '{gsub(/[0-9]+\(/,"");print}' file.log
912012091210203212  feixue11)  3600)   15 2012-09-01 12:23:12
912012091010303456  woshini)   2000)   10 2012-09-04 02:12:34
912012090910501233  sda3sd)    1200)    2  2012-09-07 12:11:46
912012090510604567  dsa4fg)    600)     5  2012-09-04 12:39:32
[root@Jason64-17~]# awk '{gsub(/[0-9]+\(/,"");gsub(/\)\W/, "");print}'file.log
912012091210203212  feixue11 3600  15  2012-09-01 12:23:12
912012091010303456  woshini  2000  10 2012-09-04 02:12:34
912012090910501233  sda3sd   1200   2  2012-09-07 12:11:46
912012090510604567  dsa4fg   600    5  2012-09-04 12:39:32
[root@Jason64-17~]# awk '{gsub(/[0-9]+\(/,"");gsub(/\)\W/, "");print$2,$3}' file.log
feixue11 3600
woshini 2000
sda3sd 1200
dsa4fg 600

再來個更笨的;是awksub函數,用了三個才把該去掉的去掉。

[root@Jason64-17~]# cat file.log
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
[root@Jason64-17~]# awk '{sub(/.*\(/,"",$2);print}' file.log
912012091210203212 feixue11) 1500(3600) 152012-09-01 12:23:12
912012091010303456 woshini) 1000(2000) 10 2012-09-0402:12:34
912012090910501233 sda3sd) 200(1200) 2 2012-09-0712:11:46
912012090510604567 dsa4fg) 500(600) 5 2012-09-0412:39:32
 [root@Jason64-17 ~]# awk'{sub(/.*\(/,"",$2);sub(/\).*\(/, " ");print}' file.log
912012091210203212 feixue11 3600) 15 2012-09-0112:23:12
912012091010303456 woshini 2000) 10 2012-09-0402:12:34
912012090910501233 sda3sd 1200) 2 2012-09-0712:11:46
912012090510604567 dsa4fg 600) 5 2012-09-0412:39:32
[root@Jason64-17~]# awk '{sub(/.*\(/,"",$2);sub(/\).*\(/, "");sub(/\).*/,"");print}' file.log
912012091210203212 feixue11 3600
912012091010303456 woshini 2000
912012090910501233 sda3sd 1200
912012090510604567 dsa4fg 600
[root@Jason64-17~]# awk '{sub(/.*\(/,"",$2);sub(/\).*\(/, "");sub(/\).*/,"");print $2,$3}' file.log
feixue11 3600
woshini 2000
sda3sd 1200
dsa4fg 600

注意,在awk裏()是有特殊意義的,需要轉義纔可以。


下面用sed解。

sed的用法也很多,我簡單的介紹幾種。

[root@Jason64-17 ~]# cat file.log
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
[root@Jason64-17 ~]# sed 's#[()]# #g' file.log
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
[root@Jason64-17 ~]# sed 's#[()]# #g' file.log|awk '{print $3,$5}'
feixue11 3600
woshini 2000
sda3sd 1200
dsa4fg 600

這個是有點像那個awkgsub的函數。

然後還可以直接匹配進行篩選

[root@Jason64-17~]# sed 's#[^(]*(\(.*\))\W.*(\(.*\)).*#\1 \2#' file.log
feixue11 3600
woshini 2000
sda3sd 1200
dsa4fg 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 3600
woshini 2000
sda3sd 1200
dsa4fg 600


以上內容僅供參考!

說給博友的話:方法很多,還請大家發動大腦,多思考下看還有沒有更好的辦法!有想法和建議的可以留言。謝謝!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章