我正在嘗試使用 awk 和 ss 的輸出來列印第四列。有時它會起作用,但有時它會錯誤地合併或拆分列。我嘗試了幾種不同的 FS 選項,這裡有兩個或多個空格,因為欄位標題包含一個空格。
這給了我第五列和一個空白標題:
$ ss -tn
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 36 172.31.19.34:22 172.115.128.85:64478
ESTAB 0 0 [::ffff:172.31.19.34]:80 [::ffff:172.115.128.85]:65446
$ ss -tn | awk -F '[[:space:]][[:space:]]+' '{print $4}'
172.115.128.86:64478
[::ffff:172.115.128.86]:65446
這裡相同的命令給了我第四列,這就是我想要的。
$ ss -tn
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 36 172.31.19.34:22 172.115.128.85:64478
$ ss -tn | awk -F '[[:space:]][[:space:]]+' '{print $4}'
Local Address:Port
172.31.19.34:22
我知道cut
可能更容易,但我正在使用,awk
因為我想做進一步的處理。
添加細節:我不確定為什麼 ss 顯示此 IPv6 樣式位址。這是從我的筆記型電腦到 apache 伺服器的連接,但我的筆記型電腦沒有 IPv6 位址。
答案1
作為穆魯暗示在一個評論,awk
可能會持續工作。可以變化的是 的輸出中的間距ss
。
結果ss -nt
1輸出了七列,標題分別是:State
, Recv-Q
, Send-Q
, Local Address
, Port
, Peer Address
, Port
。第四列和第五列之間以冒號 ( :
) 分隔;第六和第七也是同樣的情況。所有其他內容均由空格字元分隔。
所有列都在需要對齊的地方填充了空格。第四個和第六個填充在其左側,所有其他填充在右側。
可能會發生進一步的填充:
如果 的輸出
ss -nt
定向到終端:如果其行的最小長度(計算為每個字段的最長內容加上最小間距(六個字元)總和)小於終端的寬度,則每行透過均勻填充擴展到終端的寬度所有帶有空格的列;
否則,線會被打斷,並且欄位會跨線對齊(如上填充,直到終端的寬度)。
如果 的輸出
ss -nt
不定向到終端(例如,它透過管道傳輸或重定向到常規檔案),則行的實際長度定義為 80 的最小倍數,該倍數高於上面定義的最小長度。所有列均均勻地填入空格,以達到總行長度,即 80、160、240、...字元2。
因此,不能保證兩列會被兩個或多個空格分隔,這使得該序列對於分割來說不可靠。
儘管如此,您仍然可以以相當安全的方式處理 的輸出ss -tn
,注意列標題是已知且固定的,並且除了標題之外,其任何列都不應包含空格3:
ss -nt | sed '
1 s/[ ]Address:/_Address|/g # Remove the known spaces from column
# headers; also, change ":" into "|"
s/:\([^:|]*[ ]\)/|\1/g # Change the colons used as separators
# into vertical bars "|", to avoid
s/:\([^:|]*\)$/|\1/g # confusion with those in IPv6s
' | awk -v FS='\\||[ ]+' -v OFS=":" ' # Split on sequences of one or more
{ print $4,$5 } # spaces OR on any vertical bar
'
這將僅列印第四和第五列(本地位址和連接埠),以冒號分隔。請注意,使用不是預設的單一空格的欄位分隔符號awk
將識別八列而不是七列,並且如果您執行 a { $1=$1; print; }
,它將OFS
在最後一列右填充的任何行的末尾列印一個至少有一個空格。
1其他選項(例如-i
, -e
, -m
)會大幅改變 的輸出ss
。為了簡潔和清楚起見,我們將只專注於這個確切的命令。
2近似且可能不精確。但這與這個問題/答案的要點無關。
3顯然這並不能保證,我們故意不嘗試涵蓋所有不常見的情況。
答案2
為什麼 awk 欄位分隔符號不能一致運作?
是的,不可靠的是 的輸出中的空格數量ss
。
第四欄,這就是我想要的。
然後只需刪除標題 ( -H
) 並選擇第四列:
$ ss -taH | awk '{print $4}'
172.31.19.34:22
[::ffff:172.31.19.34]:80
由於標頭是固定的,只需將其添加回來(如果需要):
$ echo "Local Address:Port"
Local Address:Port
完整命令:
$ echo "Local Address:Port"; ss -tnH | awk '{print $4}'
Local Address:Port
172.31.19.34:22
[::ffff:172.31.19.34]:80
是的,您的電腦始終具有 IPv6(一個或多個)位址。如果您不需要它們,只需詢問 IPv4 位址:
$ ss -tnH4 | awk '{print $4}'
172.31.19.34:22