Sed

與 kst 一起使用的 Linux 日誌文件結構更改

  • October 29, 2014

我的文件(來自網路感測器的 tcp 轉儲)具有以下形狀:

20:06:57.049686 IP (tos 0x0, ttl 64, id 26871, offset 0, flags [DF], proto UDP (17), length 68)
e108-193.eduroam.tugraz.ac.at.34225 > e158-093.eduroam.tugraz.ac.at.personal-agent:[udp sum ok] UDP,長度 40
0x0000: 4500 0044 68f7 4000 4011 25c7 8083 d0bf E..Dh.@.@.% .....
0x0010: 8083 da24 85b1 15b3 0030 1e8b 3132 3033 ...$.....0..1203
0x0020: 3132 2e37 3836 3036 2c20 332c 2020 2030 12.78606,.3,...0
0x0030: 2e31 3533 2c20 2d30 2e31 3533 2c20 2039 .153,.-0.153,..9
0x0040: 2e39 3630 .960
20:06:57.113591 IP (tos 0x0, ttl 64, id 26872, offset 0, flags [DF], proto UDP (17), length 68)
e108-193.eduroam.tugraz.ac.at.34225 > e158-093.eduroam.tugraz.ac.at.personal-agent:[udp sum ok] UDP,長度 40
0x0000: 4500 0044 68f8 4000 4011 25c6 8083 d0bf E..Dh.@.@.% .....
0x0010: 8083 da24 85b1 15b3 0030 148f 3132 3033 ...$.....0..1203
0x0020: 3132 2e38 3336 3131 2c20 332c 2020 2d30 12.83611,.3,..-0
0x0030: 2e31 3533 2c20 2d30 2e34 3630 2c20 2039 .153,.-0.460,..9
0x0040: 2e39 3630 .960
20:06:57.188105 IP (tos 0x0, ttl 64, id 26873, offset 0, flags [DF], proto UDP (17), length 68)
e108-193.eduroam.tugraz.ac.at.34225 > e158-093.eduroam.tugraz.ac.at.personal-agent:[udp sum ok] UDP,長度 40
0x0000: 4500 0044 68f9 4000 4011 25c5 8083 d0bf E..Dh.@.@.% .....
0x0010: 8083 da24 85b1 15b3 0030 1b80 3132 3033 ...$.....0..1203
0x0020: 3132 2e38 3836 3135 2c20 332c 2020 2d30 12.88615,.3,..-0
0x0030: 2e31 3533 2c20 2d30 2e33 3036 2c20 2039 .153,.-0.306,..9
0x0040: 2e38 3037 .807 
20:06:57.200719 IP (tos 0x0, ttl 64, id 26874, offset 0, flags [DF], proto UDP (17), length 68)
e108-193.eduroam.tugraz.ac.at.34225 > e158-093.eduroam.tugraz.ac.at.personal-agent:[udp sum ok] UDP,長度 40
0x0000: 4500 0044 68fa 4000 4011 25c4 8083 d0bf E..Dh.@.@.% .....
0x0010: 8083 da24 85b1 15b3 0030 2884 3132 3033 ...$.....0(.1203
0x0020: 3132 2e39 3336 3135 2c20 332c 2020 2030 12.93615,.3,...0
0x0030: 2e31 3533 2c20 2d30 2e31 3533 2c20 2039 .153,.-0.153,..9
0x0040: 2e38 3037 .807

我需要把它轉換成這個或類似的形狀:

20:06:57.049686 26871, 120312.78606,.0.153,.-0.153,..9.960
20:06:57.113591 26872, 120312.83611,-0.153,.-0.460,..9.960
20:06:57.188105 26873, 120312.88615,-0.153,.-0.306,..9.807
20:06:57.200719 26874, 120312.93615,.0.000,.-0.153,..9.807

到目前為止,一個 vb 腳本做得很好,但現在我們需要實時顯示這些數據,所以必須有一個腳本在更新日誌時使用 grep/cut/awk 執行此操作的任何命令,因此,在完成後打開文件並在 libre-office 中使用 vbscript 不再好。

有什麼建議麼?

我重新考慮了我的方法,並決定使用H舊空間既更容易也更強大。正如您提到的文件分隔製表符而不是空格,簡單的解決方法是使用字元類而不是文字空格字元。不過,關於類的問題是它們可能會變得有點笨重,因此我通常更喜歡在使用它們時將它們包裝在替換中。我還將通過將它包裝在一個 shell 函式中,將它打包成一個簡單的命令。

又來了,又不一樣了:

#!/bin/sh
robot() (s=[:blank:];LC_ALL=C \
   sed "s/^[$s].*[$s]//;s/\.\.*/./g
   /[$s][^i$]*[^1-9d]*[d$s]*/!{H;\$!d
   };   s//,/;x;s///;s/\n//g
        s/,\.\([-1-9]*\)0*//
        s//,\1/g;s//,+.\1/g" "$@" 
)
robot "$@"            

如果從上面刪除了頂行和底行,則可以將其複制/粘貼到正在執行的與 POSIX 兼容的 shell 中,該 shell 中包含一個與 POSIX 兼容sed$PATH. 否則,上述內容可以逐字寫入$PATH. 無論哪種方式,我都可以將其稱為INPUT| robotorrobot <infilerobot infile1 infile[2-9] -。像:

robot <<\DATA
20:06:57.049686 IP (tos 0x0, ttl 64, id 26871, offset 0, flags [DF], proto UDP (17), length 68)
   e108-193.eduroam.tugraz.ac.at.34225 > e158-093.eduroam.tugraz.ac.at.personal-agent: [udp sum ok] UDP, length 40
   0x0000:  4500 0044 68f7 4000 4011 25c7 8083 d0bf  E..Dh.@.@.%.....
   0x0010:  8083 da24 85b1 15b3 0030 1e8b 3132 3033  ...$.....0..1203
   0x0020:  3132 2e37 3836 3036 2c20 332c 2020 2030  12.78606,.3,...0
   0x0030:  2e31 3533 2c20 2d30 2e31 3533 2c20 2039  .153,.-0.153,..9
   0x0040:  2e39 3630                                .960
DATA

而舊版本列印…

20:06:57.049686,26871,.0.120312.78606,.3,.0.153,-0.153,.9.960

這個列印…

20:06:57.049686,26871,120312.78606,+.153,-.153,9.960

它現在從各個欄位中去除前導*.dots0zeroes*.3 ,並刪除它之前獲得的虛假欄位,該欄位未包含在您的輸出中。它還+為可能以*-dash 開頭*的欄位的輸出添加符號。

也許它做的太多了——我真的不知道所有這些領域應該如何結合在一起,這只是我最好的猜測。我試圖在下面分解它,但如果你想看到它出於任何原因做一些不同的事情,請不要猶豫。

字元類[:blank:]匹配由語言環境定義的任何水平空白字元 - 因此它可以是空格或製表符,不會有任何區別。考慮到語言環境,我決定在C這裡明確指定語言環境,因為在進行文本處理時它始終是最明智的做法 - 在C語言環境中,每個輸入字節都保證匹配單個字元*(這可能意味著很多sed時候它會做類似的事情.*)*。但是,函式中定義的任何狀態都只對函式是本地的,並且不會影響執行環境,除了列印到stdout.

流動:

如果該行以一個開頭,則腳本的第一行將sed刪除從第一個到最後出現的一系列字元。然後它還會用單個 s替換任何系列的s 。[[:blank:]] .dot``.dot

下一行有點毛茸茸。它是一個單一地址,用於處理多階段s///替換,使用空地址來引用腳本中的最後一個非空地址。

/[$s][^i$]*[^d1-9]*[d$s]*/

地址中唯一的明確匹配是至少一個空白 - 匹配*次或多次出現內的所有其他序列- 因此它無法匹配根本不包含空白的行。這意味著它只匹配塊標題,因為我們剛剛從任何以 1 開頭的行中刪除了所有空格。

所以我要做的第一件事是將它與非標題行進行比較,H如果它們!不匹配,則將它們放在舊空間中,並從輸出$!d中刪除所有!不是最後一個的行。$所以$這裡的最後一行與腳本其餘部分的所有塊標題混為一談,因為從這裡開始,這些是唯一sed將應用任何規則的行。

考慮將該地址與標題行進行比較:

20:06:57.049686 IP (tos 0x0, ttl 64, id 26871, offset 0, flags [DF], proto UDP (17), length 68)
  • [$s]- 匹配第一個空白 - 就在之前IP
  • [^i$]*- 匹配64,[[:blank:]].
  • [^d1-9]* - matches the 我`。
  • [d$s]*- 匹配d[[:blank:]]

因此,當我這樣做時,s//,/所有這些都被逗號替換。這不會影響我們剛剛通過的最後一行,因為它無法匹配前導[[:blank:]]。即使是這樣,任何更改都將無關緊要,因為對於最後一行,唯一列印的副本是在H舊空間中等待我們的副本,我們僅在x更改後才進行操作。這是下一個命令 - 並且普遍適用 - 所以我們現在正在使用看起來像……的模式空間

20:06:57.049686,26871, offset 0, flags [DF], proto UDP (17), length 6\
8)\n40\nE.Dh.@.@.%.\n.$.0.1203\n12.78606,.3,.0\n.153,.-0.153,.9\n.960$

…它代表了已經應用於前一個塊標題的編輯以及H此後所有行的編輯 - 正如您所看到的那樣,\n那裡用 ewline 轉義符分隔。

讓我們再次將其與我們的長地址進行比較:

  • [$s]- 匹配[[:blank:]]之前出現的第一個offset
  • [^i$]*- 一直匹配到但不包括第一個出現的$字元。
  • [^d1-9]*- 匹配.0.
  • [d$s]*- 什麼都不匹配。

所以,和以前一樣,s///抹去所有這些。在刪除所有\newlines之後s/\n//g,現在模式空間看起來像:

20:06:57.049686,26871,120312.78606,.3,.0.153,.-0.153,.9.960

…這幾乎是舊版本留下的地方。但是我對遞歸匹配很感興趣,所以我添加了一點。你不應該,雖然我可能會做得更好,因為我發現它有漏洞,最後一點可能更好地在第二個過濾器中完成,使用針對 csv 的新腳本。儘管如此,它肯定適用於範例輸入,並且可能會適用更多,但我想我可能會拒絕它,以防萬一它沒有或萬一它確實但不符合您的期望。最後兩行可以很容易地刪除,以獲得與您檢查此答案時接受的輸出一致的輸出 - 如上所示。

s/,\.\([-1-9]*\)0*//

這將刪除第一個出現的*, 逗號後跟.dot的序列,然後是零個或多個-dash*或非零的數字和任何尾隨零。這會,.3從輸出中刪除該欄位。

第二次應用一個global 標誌並保存它\1不會被刪除s//,\1/,它會轉換:

20:06:57.049686,26871,120312.78606,.0.153,.-0.153,.9.960

…進入…

20:06:57.049686,26871,120312.78606,.153,-.153,9.960

又一次在局部應用g了一個添加的+.like s//,+./g,它進一步修改了模式空間以讀取:

20:06:57.049686,26871,120312.78606,+.153,-.153,9.960

…這是在開始下一行循環stdout之前自動列印到的內容。sed

如果任何讀者實際上已經做到了這一點並且對我所說的舊版本感到好奇,你會發現它並在編輯歷史中詳細解釋它是如何工作的

將此腳本提供給您的整個範例輸入將得到:

20:06:57.049686,26871,120312.78606,+.153,-.153,9.960
20:06:57.113591,26872,120312.83611,-.153,-.460,9.960
20:06:57.188105,26873,120312.88615,-.153,-.306,9.807
20:06:57.200719,26874,120312.93615,+.153,-.153,9.807

引用自:https://unix.stackexchange.com/questions/163857