スペースで区切られた単語のリストを端末の幅に合うテーブル列に縮小する方法

スペースで区切られた単語のリストを端末の幅に合うテーブル列に縮小する方法

次のようにスペースで区切られた一連の単語をテーブル形式で出力し、1行ずつ埋め、端末の幅を超えずに利用可能なスペースを最適に活用したいと思います。

+-----------------------------------------------+
|polite      babies      embarrass   rightful   | 
|aspiring    scandalous  mut         disgusted  |
|bell        deeply      writer      jumbled    |
|respired    craggy                             |

(ボックスは端末の幅を説明し、出力の一部ではありません)

fold思い出させる命令はcolumnこうです。

$ fold words -s -w $COLUMNS | column -t

$COLUMNSこれはほぼうまく機能しますが、出力は最初にその幅内で縮小され、次にスペースを増やして整列するため(ターミナル幅)よりも広くなります。

私にとって必要なのは、この2つが1つにまとめられた効果です。これを実行できるコマンドラインツール(または組み込みシェル)はありますか?

ベストアンサー1

各列の幅と受け入れることができる列の最大数を決定するには、可能なすべての列数(2からCOLUMNS / 2まで)の合計幅を取得する必要があるようです。

そしてperl

#! /usr/bin/perl
use List::Util qw(sum);

$/ = undef;
@word = <> =~ /\S+/g;
$max = $ENV{COLUMNS}/2;
for ($i = 0; $i <= $#word; $i++) {
  $l = length $word[$i];
  for ($c = 2; $c <= $max; $c++) {
    if ($l > $w[$c][$i%$c]) {
      $w[$c][$i%$c] = $l
    }
  }
}
for ($c = $max; $c > 1; $c--) {
  last if $c + sum(@{$w[$c]}) - 1 <= $ENV{COLUMNS}
}
if($c > 1) {
  @w = @{$w[$c]};
  for ($i = 0; $i <= $#word; $i++) {
    if (($i+1)%$c && $i < $#word) {
      printf "%-*s ", $w[$i%$c], $word[$i]
    } else {
      print "$word[$i]\n"
    }
  }
} else {
  print "$_\n" for @word
}

例:

$ lorem -w 50 | COLUMNS=60 that-script
minima   aut     veritatis laudantium qui      voluptatem
est      nostrum quis      enim       placeat  hic
voluptas ab      ratione   sit        hic      sit
pariatur et      provident voluptas   aut      odio
aut      vero    atque     voluptatem amet     voluptatem
ipsum    iusto   omnis     tenetur    ratione  ratione
illo     ea      odit      excepturi  quisquam aut
nobis    porro   incidunt  corrupti   maxime   ad
est      sunt

ASCII以外のテキストについては、以下を参照してください。文字列の表示幅を取得します。文字列の表示幅を決定します。それは次のとおりです。

#! /usr/bin/perl
use Text::CharWidth qw(mbswidth);
use List::Util qw(sum);

$/ = undef;
@word = <> =~ /\S+/g;
$max = $ENV{COLUMNS}/2;
for ($i = 0; $i <= $#word; $i++) {
  $l = mbswidth $word[$i];
  for ($c = 2; $c <= $max; $c++) {
    if ($l > $w[$c][$i%$c]) {
      $w[$c][$i%$c] = $l
    }
  }
}
for ($c = $max; $c > 1; $c--) {
  last if $c + sum(@{$w[$c]}) - 1 <= $ENV{COLUMNS}
}
if($c > 1) {
  @w = @{$w[$c]};
  for ($i = 0; $i <= $#word; $i++) {
    if (($i+1)%$c && $i < $#word) {
      printf $word[$i] . " " x ($w[$i%$c]+1-mbswidth($word[$i]))
    } else {
      print "$word[$i]\n"
    }
  }
} else {
  print "$_\n" for @word
}

おすすめ記事