다음과 같이 공백으로 구분된 일련의 단어를 테이블 형식으로 출력하고, 한 줄씩 채워서 터미널 너비를 초과하지 않고 사용 가능한 공간을 최적으로 활용하고 싶습니다.
+-----------------------------------------------+
|polite babies embarrass rightful |
|aspiring scandalous mut disgusted |
|bell deeply writer jumbled |
|respired craggy |
(상자는 터미널의 너비를 설명하며 출력의 일부가 아닙니다)
fold
생각나는 명령은 column
이렇습니다.
$ fold words -s -w $COLUMNS | column -t
$COLUMNS
이것은 거의 작동하지만 출력은 먼저 해당 너비 내에서 축소된 다음 공백을 늘려 정렬하기 때문에 (터미널 너비)보다 넓어집니다 .
나에게 필요한 것은 이 둘이 하나로 결합된 효과이다. 이를 수행할 수 있는 명령줄 도구(또는 내장 쉘)가 있습니까?
답변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
}
답변2
동일한 간격의 열을 생성하려면 BSD를 사용할 수 있습니다.rs
(또한 Debian 및 파생 제품(적어도)으로 포팅되었으며 패키지로 사용 가능) 또는 BSD column
( bsdmainutils
Debian의 패키지):
tr -s '[:space:]' '[ *]' | rs -w "$COLUMNS"
tr -s '[:space:]' '[\n*]' | column -xc "$COLUMNS"
예(수직선은 60열 와이드 화면의 가장자리를 표시하는 데 사용되며 출력의 일부가 아닙니다):
$ lorem -w 30 | tr -s '[:space:]' '[ *]' | rs -w60
earum aspernatur ipsa sed ┃
quod sit esse quisquam ┃
animi reprehenderit porro et ┃
delectus neque esse quia ┃
pariatur amet iste voluptatem ┃
provident praesentium et sint ┃
quo animi doloribus veritatis ┃
iusto alias ┃
를 사용하면 열 사이의 공간을 줄이는 rs
옵션을 추가할 수 있지만 -z
이에 따라 열 수가 최적화되지는 않습니다. 예를 들어 위에서는 (AND rs -zw60
)가 제공됩니다.
earum aspernatur ipsa sed ┃
quod sit esse quisquam ┃
animi reprehenderit porro et ┃
delectus neque esse quia ┃
pariatur amet iste voluptatem ┃
provident praesentium et sint ┃
quo animi doloribus veritatis ┃
iusto alias ┃
바꾸다:
earum aspernatur ipsa sed quod ┃
sit esse quisquam animi reprehenderit ┃
porro et delectus neque esse ┃
quia pariatur amet iste voluptatem ┃
provident praesentium et sint quo ┃
animi doloribus veritatis iusto alias ┃
또한 멀티바이트 문자나 너비가 0이거나 두 배인 문자에도 작동하지 않습니다.
기본적으로 열 사이에는 최소 2개의 공백이 있습니다. 를 사용하여 1로 변경할 수 있습니다 -g 1
.