Awk
awk 將 TSV 表轉換為網格表
我想將帶有製表符作為分隔符的文本表(即基本上是 TSV 文件)轉換為在所有邊界(內部和外部)和文本換行上都有線條的網格表。
下面是輸入
TrackId peerId Cause Count ESS_RSM pra4.pra.pnc100.tpp240.6pppsetwork.prg 40009 Response is not received from server 1401 ESS_RSM pra5.pra.pnc100.tpp240.6pppsetwork.prg 40009 Response is not received from server 1398 ESS_RSM pra3.pra.pnc100.tpp240.6pppsetwork.prg 40009 Response is not received from server 1347 ESS_RSM pra1.pra.pnc100.tpp240.6pppsetwork.prg 40009 Response is not received from server 1412 ESS_RSM pra2.pra.pnc100.tpp240.6pppsetwork.prg 40009 Response is not received from server 1355 ESS_RSM pra6.pra.pnc100.tpp240.6pppsetwork.prg 40009 Response is not received from server 1416
大片的空白是製表符;“未從伺服器收到響應”中的空格是空格。輸出應如下所示:
┌────────┬────────────────────────────────────────┬────────────────────────────┬────────┐ │TrackId │ peerId │ Cause │ Count │ ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤ │ESS_RSM │ pra4.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not │ 1,401 │ │ │ │ received from server │ │ ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤ │ESS_RSM │ pra5.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not │ 1,398 │ │ │ │ received from server │ │ ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤ │ESS_RSM │ pra3.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not │ 1,347 │ │ │ │ received from server │ │ ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤ │ESS_RSM │ pra1.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not │ 1,412 │ │ │ │ received from server │ │ ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤ │ESS_RSM │ pra2.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not │ 1,355 │ │ │ │ received from server │ │ ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤ │ESS_RSM │ pra6.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not │ 1,416 │ │ │ │ received from server │ │ └────────┴────────────────────────────────────────┴────────────────────────────┴────────┘
或者可能
TrackId │ peerId │ Cause │ Count │ ────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤ │ pra4.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from │ │ ESS_RSM │ work.prg │ server │ 1,401 │ ────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤ │ pra5.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from │ │ ESS_RSM │ work.prg │ server │ 1,398 │ ────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤ │ pra3.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from │ │ ESS_RSM │ work.prg │ server │ 1,347 │ ────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤ │ pra1.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from │ │ ESS_RSM │ work.prg │ server │ 1,412 │ ────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤ │ pra2.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from │ │ ESS_RSM │ work.prg │ server │ 1,355 │ ────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤ │ pra6.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from │ │ ESS_RSM │ work.prg │ server │ 1,416 │ ────────┴────────────────────────────────┴──────────────────────────────────────┴─────────┘
我嘗試了下面的程式碼,但輸出不是我想要的。
awk '{print "<table>"} {print "<tr>"; for(i=1;i<=NF;i++) print "|" $i "|";print "|"} END {PRINT "|"}' file
使用一些古老的 Unix 實用程序,
#!/bin/sh { printf '%s\n' '' .TS 'allbox;LLLL,LLLR.' awk -v sq="'" ' BEGIN { FS = OFS = "\t"; fmt = "%" sq "d" } NR==1 { print } NR>1 { print $1, "T{" print $2 print "T}", "T{" print $3 print "T}", sprintf(fmt, $4) } ' "$@" printf '%s\n' .TE '.pl 0' } | tbl | nroff 2> /dev/null
解釋:
nroff
是古老的 Unix 文本處理器。例如,它將採取Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
作為輸入,並產生
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
作為輸出。
tbl``nroff
是一個支持——你猜對了——表生成的前端。.TS
是“表開始”。allbox
很明顯:在每個單元格周圍畫一個框。LLLL
表示第一行中的所有單元格都是左對齊的;LLLR
表示第四個單元格對於所有後續行都是右對齊的。我想這就是您查看範例輸出想要的結果。-v sq="'"
創建一個名為的變數sq
,其值為單引號。這是在 awk 程序中使用單引號的一種方法,在The GNU Awk User’s Guide中有建議。- 設置
FS
為選項卡,因為輸入是 TSV。設置OFS
為選項卡,因為這是tbl
預期的(預設情況下)。fmt = "%" sq "d"
設置fmt
為%'d
,可用於[s]printf
輸出帶有千位分隔符的整數。(我假設你想要這個,因為你展示了它。)- 通過未修改的第一行(標題)。
- 對於所有其他行(數據),使用
T{
和T}
標記進行$2
文本$3
換行。(我假設您只需要第二列和第三列,因為第一列和第四列只包含短字元串。)列印$4
每三位插入逗號的值。.TE
是“桌端”。.pl
是頁長。這有點像一個kludge。預設情況下,nroff
將用空行填充其輸出,以使整體輸出為 66 行的倍數。通過將頁面長度設置為零,我們可以抑制它。- 上述 (
printf
,awk
和printf
) 的輸出通過管道傳輸到tbl
andnroff
。- 儘管標準輸出是合理的,但出現錯誤消息時我遇到了很多問題,因此我將 stderr 發送到 bitbucket。如果你得到奇怪的結果,你應該做的第一件事是擺脫 stderr 重定向並查看錯誤消息(儘管它們可能不是很有幫助)。
指示:
- 把上面的程式碼放到一個文件中。例如,呼叫它
gman
。- 做
$ chmod +x gman
使其可執行。
- 如果您的數據在文件中(例如,稱為
shap
),請執行$ ./gman shap
您可能希望將輸出重定向到文件:
$ ./gman shap > grid_table
- 如果您在第一列中獲取所有數據,則意味著您的輸入文件中實際上沒有製表符(只有空格)。編輯它以用製表符替換空格(空格)。
- 如果您的數據是由其他程序生成/生成的,例如數據庫查詢,您可以執行
$ db_query > tmp $ ./gman tmp
(然後可選
rm tmp
,如果您不需要它用於其他任何事情),或者只是$ db_query | ./gman
- 如果將
gman
文件移動(或複制)到搜尋路徑中的目錄,則只需鍵入gman
(不帶**./
**)即可執行它。有 很多關於此的文件;如果您搜尋,很容易找到。例如,對於問題中顯示的輸入,我得到
┌───────────┬─────────────────────────────────┬───────────────┬───────┐ │ TrackId │ peerId │ Cause │ Count │ ├───────────┼─────────────────────────────────┼───────────────┼───────┤ │ESS_RSM │ pra4.pra.pnc100.tpp240.6pppset‐ │ 40009 Re‐ │ 1,401 │ │ │ work.prg │ sponse is not │ │ │ │ │ received from │ │ │ │ │ server │ │ ├───────────┼─────────────────────────────────┼───────────────┼───────┤ │ESS_RSM │ pra5.pra.pnc100.tpp240.6pppset‐ │ 40009 Re‐ │ 1,398 │ │ │ work.prg │ sponse is not │ │ │ │ │ received from │ │ │ │ │ server │ │ ├───────────┼─────────────────────────────────┼───────────────┼───────┤ │ESS_RSM │ pra3.pra.pnc100.tpp240.6pppset‐ │ 40009 Re‐ │ 1,347 │ │ │ work.prg │ sponse is not │ │ │ │ │ received from │ │ │ │ │ server │ │ ├───────────┼─────────────────────────────────┼───────────────┼───────┤ │ESS_RSM │ pra1.pra.pnc100.tpp240.6pppset‐ │ 40009 Re‐ │ 1,412 │ │ │ work.prg │ sponse is not │ │ │ │ │ received from │ │ │ │ │ server │ │ ├───────────┼─────────────────────────────────┼───────────────┼───────┤ │ESS_RSM │ pra2.pra.pnc100.tpp240.6pppset‐ │ 40009 Re‐ │ 1,355 │ │ │ work.prg │ sponse is not │ │ │ │ │ received from │ │ │ │ │ server │ │ ├───────────┼─────────────────────────────────┼───────────────┼───────┤ │ESS_RSM │ pra6.pra.pnc100.tpp240.6pppset‐ │ 40009 Re‐ │ 1,416 │ │ │ work.prg │ sponse is not │ │ │ │ │ received from │ │ │ │ │ server │ │ └───────────┴─────────────────────────────────┴───────────────┴───────┘
作為輸出。有一些技巧可以使列(例如第三個)更寬;讓我知道你想知道什麼。
警告:當你執行它時
tbl
,nroff
將會
- 讀取所有數據,
- 將其儲存在記憶體和/或臨時文件中,
- 計算列寬,然後
- 輸出所有數據。
如果你有很多 數據,你可能會溢出臨時儲存的限制,命令會失敗。您可以通過將輸入分解為更小的文件來獲得可用的結果。
警告:如果您的文件包含
T{
orT}
,或以句點 (.
) 或單引號 ('
) 開頭的值,您可能會得到奇怪的結果。