我可以對列選項卡大小進行後格式化,以使間距成為 Linux 中的最小公分母嗎?

我可以對列選項卡大小進行後格式化,以使間距成為 Linux 中的最小公分母嗎?

我可以用來stat建立一個 ls 輸出,顯示兩種格式的權限訊息,這很方便:

stat --printf="%A\t%a\t%h\t%U\t%G\t%s\t%.19y\t%n\n" . .*

drwxr-xr-x      755     4       boss    boss    4096    2021-10-29 22:49:12     .
drwxr-xr-x      755     4       boss    boss    4096    2021-10-29 22:49:12     .
drwxr-xr-x      755     36      boss    boss    4096    2021-11-01 11:30:24     ..
-rw-r--r--      644     1       boss    boss    97708   2021-11-01 11:30:16     .custom
-rw-r--r--      644     1       boss    boss    4013    2021-10-11 22:04:04     .custom-dk

然而,列之間的間距\t很好,但相當“間隙”。這讓我很好奇,是否有一種通用方法可以對這樣的任何輸出進行後處理,使得列將處於單空間間隙的最低公分母,即是否有一種通用方法可以將上面的內容調整為類似於下面的內容使用awkorsed或類似的(如果可能的話,我也將數字列右對齊作為“理想”輸出)?

drwxr-xr-x 755  4 boss boss  4096 2021-10-29 22:49:12 .
drwxr-xr-x 755  4 boss boss  4096 2021-10-29 22:49:12 .
drwxr-xr-x 755 36 boss boss  4096 2021-11-01 11:30:24 ..
-rw-r--r-- 644  1 boss boss 97708 2021-11-01 11:30:16 .custom
-rw-r--r-- 644  1 boss boss  4013 2021-10-11 22:04:04 .custom-dk

答案1

關於你的問題中的“或 sed” - sed 是用於對單個字串進行簡單 s/old/new/ 轉換的正確工具,你所做的不是那樣的,所以 sed 甚至不應該是一個選項考慮。

使用 2 遍方法,首先確定每列的最大寬度和對齊方式,然後在列印時使用它們,在每個 Unix 機器上的任何 shell 中使用任何 awk:

$ cat tst.awk
BEGIN { FS="\t" }
NR==FNR {
    for (i=1; i<=NF; i++) {
        align[i] = ( $i ~ /^[0-9]+$/ ? "" : "-" )
        width[i] = ( length($i) > width[i] ? length($i) : width[i] )
    }
    next
}
{
    for (i=1; i<NF; i++) {
        printf "%" align[i] width[i] "s ", $i
    }
    print $NF
}

$ awk -f tst.awk file file
drwxr-xr-x 755  4 boss boss  4096 2021-10-29 22:49:12 .
drwxr-xr-x 755  4 boss boss  4096 2021-10-29 22:49:12 .
drwxr-xr-x 755 36 boss boss  4096 2021-11-01 11:30:24 ..
-rw-r--r-- 644  1 boss boss 97708 2021-11-01 11:30:16 .custom
-rw-r--r-- 644  1 boss boss  4013 2021-10-11 22:04:04 .custom-dk

上面假設您的最後一列始終是左對齊的,如果情況並非如此,請告訴我們,因為無論哪種方式處理都不難。它還假設列的對齊方式可以由輸入最後一行欄位中的值(數字或非數字)決定。

如果輸入必須來自管道而不是檔案(因此您無法開啟輸入兩次),那麼您可以將輸入儲存在陣列中並在 END 部分中列印:

$ cat tst.awk
BEGIN { FS = "\t" }
{
    for (i=1; i<=NF; i++) {
        width[i] = ( length($i) > width[i] ? length($i) : width[i] )
        align[i] = ( $i ~ /^[0-9]+$/ ? "" : "-" )
        vals[NR,i] = $i
    }
}
END {
    for (n=1; n<=NR; n++) {
        for (i=1; i<NF; i++) {
            printf "%" align[i] width[i] "s ", vals[n,i]
        }
        print vals[n,NF]
    }
}

然後將其稱為:

$ stat --printf="%A\t%a\t%h\t%U\t%G\t%s\t%.19y\t%n\n" . .* | awk -f tst.awk

答案2

您可以使用column -t your_file(但據我所知,它沒有得到正確的合理位)

輸出:

drwxr-xr-x  755  4   boss  boss  4096   2021-10-29  22:49:12  .
drwxr-xr-x  755  4   boss  boss  4096   2021-10-29  22:49:12  .
drwxr-xr-x  755  36  boss  boss  4096   2021-11-01  11:30:24  ..
-rw-r--r--  644  1   boss  boss  97708  2021-11-01  11:30:16  .custom
-rw-r--r--  644  1   boss  boss  4013   2021-10-11  22:04:04  .custom-dk

相關內容