Linux で間隔が最小公分母になるように列タブのサイズを後からフォーマットできますか?

Linux で間隔が最小公分母になるように列タブのサイズを後からフォーマットできますか?

両方の形式の権限情報を表示する ls 出力を作成するために使用できますstat。これは便利です。

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が、これは問題ありませんが、かなり「隙間」があります。これにより、列が 1 スペースのギャップの最小公分母になるように、このような出力を後処理する一般的な方法があるかどうかが気になりました。つまり、 または などを使用して、上記を以下のように調整する一般的な方法はありますかawk(sed可能であれば、列数だけを「理想的な」出力として右揃えにしています)。

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 ボックスの任意のシェルで任意の 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

上記では、最後の列が常に左揃えになることを前提としていますが、そうでない場合は、どちらの方法でも処理は難しくないのでお知らせください。また、列の配置は、入力の最後の行のフィールドの値 (数値かどうか) によって決定できることも前提としています。

入力がファイルではなくパイプから取得される必要がある場合 (つまり、入力を 2 回開くことができない場合)、入力を配列に保存し、それを 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

関連情報