Bash
如何從包含製表符和空格的文本創建統一列?
以最簡單的形式,假設我有一個名為
file.txt
. 的內容file.txt
如下所示:Source Destination Maximum To Maximum From Average Total Average To Average From (192.168.1.1) (192.168.1.2) 202.89 Kbps 0 bps 645 bps 645 bps 0 bps
我嘗試了該
column
命令的多種變體,但均無濟於事。我怎樣才能使這個輸出看起來像這樣:Source Destination Maximum To Maximum From Average Total Average To Average From (192.168.1.1) (192.168.1.2) 202.89 Kbps 0 bps 645 bps 645 bps 0 bps
我覺得我應該知道如何做到這一點,但我目前正在畫一個空白,到目前為止還沒有發現任何按預期工作的東西。
**編輯:**下面的評論和答案
sed
非常適合我的原始範例(我實際上更喜歡評論中的解決方案,因為它更簡單並且不涉及管道tr
)。話雖如此,這兩種解決方案在多行文件上的性能完全相同。實際file.txt
將包括數百行不同長度的 IPv4 地址。sed
到目前為止,兩種解決方案都在原始(更準確)上返回了以下結果file.txt
:原始文件.txt:
Source Destination Maximum To Maximum From Average Total Average To Average From (10.10.10.21) (192.168.123.122) 18.90 Kbps 0 bps 131 bps 131 bps 0 bps (10.10.10.22) (192.168.123.122) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps (10.10.10.23) (192.168.123.123) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps (192.168.123.123) (192.52.168.123) 0 bps 22.84 Kbps 1.17 Kbps 0 bps 1.17 Kbps (192.168.123.124) (192.52.168.123) 0 bps 10.87 Kbps 19 bps 0 bps 19 bps
更新了 file.txt(到目前為止使用了兩種建議的解決方案之後):
Source Destination Maximum To Maximum From Average Total Average To Average From (10.10.10.21) (192.168.123.122) 18.90 Kbps 0 bps 131 bps 131 bps 0 bps (10.10.10.22) (192.168.123.122) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps (10.10.10.23) (192.168.123.123) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps (192.168.123.123) (192.52.168.123) 0 bps 22.84 Kbps 1.17 Kbps 0 bps 1.17 Kbps (192.168.123.124) (192.52.168.123) 0 bps 10.87 Kbps 19 bps 0 bps 19 bps
是否有更新的解決方案可以解釋這個抵消警告?
腳本基於 OP 的範例數據。
sed ' s/\s\s\+/:/g s/\([a-z)]\)\s\([(0-9A]\)/\1:\2/g ' file.txt | column -s: -t
首先更改容易找到的分隔符(2 步或更多
\s
步):
第二個找到剩餘的可能分隔符:
- 小寫字母和數字之間
- 後
)
- 前
A
使用列分隔符格式化字元串
:
下面的 perl 腳本將輸入轉換為製表符分隔的欄位,這依賴於前兩個欄位每個只有一個“單詞”而其餘欄位每個都有兩個“單詞”的知識。然後將其輸出通過管道傳輸到
column -s $'\t' -t
這是一種非常笨拙和蠻力的方法,但它確實有效。
#! /usr/bin/perl use strict; while(<>) { my (@F, @fields, $i); @F=split; $fields[0] = $F[0] ; $fields[1] = $F[1] ; for $i (0..4) { $fields[$i + 2] = $F[$i*2 + 2] . ' ' . $F[$i*2 + 3]; } print join("\t",@fields),"\n"; }
它是這樣使用的:
$ ./bandwidth.pl bandwidth.txt | column -s $'\t' -t Source Destination Maximum To Maximum From Average Total Average To Average From (10.10.10.21) (192.168.123.122) 18.90 Kbps 0 bps 131 bps 131 bps 0 bps (10.10.10.22) (192.168.123.122) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps (10.10.10.23) (192.168.123.123) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps (192.168.123.123) (192.52.168.123) 0 bps 22.84 Kbps 1.17 Kbps 0 bps 1.17 Kbps (192.168.123.124) (192.52.168.123) 0 bps 10.87 Kbps 19 bps 0 bps 19 bps
順便說一句,這是一個很好的例子,說明為什麼使用也在被定界的欄位中的定界符(例如空格)從來都不是一個好主意。它只會讓事情變得比他們需要的更困難……並且沒有可靠的方法來區分分隔符和不需要提前了解文件內容和結構的欄位內容。