Dear all,
Following some back and forth on how disklabel output should be
formatted, I proposed to Kenneth to extend the column(1) utility. All that
was missing is the ability to right justify. I've longed for this
feature for a while: I often use 'column -t' to prettify data coming
from an awk pipeline.
Example:
job@vurt ~$ netstat -r | column -t -r | tail -5
ff01::%iwm0/32 fe80::4708:d2be:9a Um 0 3 - 4
iwm0
ff01::%lo0/32 localhost Um 0 1 32768 4
lo0
ff02::/16 localhost UGRS 0 1 32768 8
lo0
ff02::%iwm0/32 fe80::4708:d2be:9a Um 0 3 - 4
iwm0
ff02::%lo0/32 localhost Um 0 1 32768 4
lo0
Patch courtesy of Kenneth R Westerback. OK?
Index: column.1
===================================================================
RCS file: /cvs/src/usr.bin/column/column.1,v
retrieving revision 1.18
diff -u -p -r1.18 column.1
--- column.1 24 Oct 2016 13:53:05 -0000 1.18
+++ column.1 4 Jul 2018 10:27:54 -0000
@@ -40,6 +40,7 @@
.Nm column
.Op Fl tx
.Op Fl c Ar columns
+.Op Fl r Op Ar list
.Op Fl s Ar sep
.Op Ar
.Sh DESCRIPTION
@@ -66,6 +67,16 @@ The options are as follows:
Output is formatted for a display
.Ar columns
wide.
+.It Fl r Op Ar list
+Table mode will right justify the column contents for the
+specified columns.
+.Ar list
+is a list of comma separated column numbers or column ranges.
+Column numbers start at 1.
+The list must not contain whitespace.
+If no
+.Ar list
+is provided then all columns will be right justified.
.It Fl s Ar sep
Specify a set of characters to delimit columns for the
.Fl t
Index: column.c
===================================================================
RCS file: /cvs/src/usr.bin/column/column.c,v
retrieving revision 1.26
diff -u -p -r1.26 column.c
--- column.c 22 Jun 2018 12:27:00 -0000 1.26
+++ column.c 4 Jul 2018 10:28:00 -0000
@@ -47,7 +47,8 @@
void c_columnate(void);
void *ereallocarray(void *, size_t, size_t);
void input(FILE *);
-void maketbl(void);
+int rightjustify(const char *, const int);
+void maketbl(const int, const char *);
void print(void);
void r_columnate(void);
__dead void usage(void);
@@ -69,8 +70,8 @@ main(int argc, char *argv[])
{
struct winsize win;
FILE *fp;
- int ch, tflag, xflag;
- char *p;
+ int ch, rflag, tflag, xflag;
+ char *p, *rcols;
const char *errstr;
setlocale(LC_CTYPE, "");
@@ -87,14 +88,19 @@ main(int argc, char *argv[])
if (pledge("stdio rpath", NULL) == -1)
err(1, "pledge");
- tflag = xflag = 0;
- while ((ch = getopt(argc, argv, "c:s:tx")) != -1) {
+ rcols = NULL;
+ rflag = 0; tflag = xflag = 0;
+ while ((ch = getopt(argc, argv, "c:r::s:tx")) != -1) {
switch(ch) {
case 'c':
termwidth = strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr != NULL)
errx(1, "%s: %s", errstr, optarg);
break;
+ case 'r':
+ rflag = 1;
+ rcols = optarg;
+ break;
case 's':
if ((separator = reallocarray(NULL, strlen(optarg) + 1,
sizeof(*separator))) == NULL)
@@ -139,7 +145,7 @@ main(int argc, char *argv[])
return eval;
if (tflag)
- maketbl();
+ maketbl(rflag, rcols);
else if (*maxwidths >= termwidth)
print();
else if (xflag)
@@ -207,18 +213,69 @@ print(void)
puts(table[row]->content);
}
+int
+rightjustify(const char *rcols, const int col)
+{
+ const char *errstr;
+ char c, *num, *temp;
+ long long ch, rangestart;
+ unsigned int i;
+
+ if (rcols == NULL)
+ return 1;
+
+ temp = strdup(rcols);
+ num = temp;
+ rangestart = -1;
+
+ c = 0;
+ for (i = 0; i <= strlen(rcols); i++) {
+ ch = temp[i];
+ if (ch == ',' || ch == '-')
+ temp[i] = '\0';
+ if (temp[i] != '\0')
+ continue;
+
+ c = strtonum(num, 1, INT_MAX, &errstr);
+ if (errstr != NULL)
+ break;
+ c--; /* Users are 1-based. Reality is 0-based. */
+
+ if (c == col)
+ goto found;
+ if (ch == '-') {
+ rangestart = c;
+ } else if ((ch == ',' || ch == '\0') && rangestart != -1) {
+ if (rangestart <= col && c >= col)
+ goto found;
+ rangestart = -1;
+ }
+ num = temp + i + 1;
+ }
+
+ free(temp);
+ return 0;
+found:
+ free(temp);
+ return 1;
+}
void
-maketbl(void)
+maketbl(const int rflag, const char *rcols)
{
struct field **row;
int col;
for (row = table; entries--; ++row) {
- for (col = 0; (*row)[col + 1].content != NULL; ++col)
- printf("%s%*s ", (*row)[col].content,
- maxwidths[col] - (*row)[col].width, "");
- puts((*row)[col].content);
+ for (col = 0; (*row)[col].content != NULL; ++col) {
+ if (rflag && rightjustify(rcols, col))
+ printf("%*s ", maxwidths[col],
+ (*row)[col].content);
+ else
+ printf("%-*s ", maxwidths[col],
+ (*row)[col].content);
+ }
+ putchar('\n');
}
}