q icon indicating copy to clipboard operation
q copied to clipboard

Add a fixed width input mode

Open alahijani opened this issue 6 years ago • 2 comments

Maybe consider adding an option to parse pretty printed input, to complement -b for pretty printed output.

I use q on kubectl output, but when one of the values has a space in it, it breaks the parsing:

$ kubectl get ingress
NAME             HOSTS              ADDRESS       PORTS     AGE
cms-api          cms.internal       10.215.0.40   80, 443   20d
content-portal   content.internal   10.215.0.40   80, 443   20d

Usually q -HOb 'select * from -' is a no-op, but in this case:

$ kubectl get ingress | q -HOb 'select * from -'
NAME           HOSTS                 ADDRESS     PORTS AGE c6
cms-api        cms.internal          10.215.0.40 80,   443 20d
content-portal content.internal      10.215.0.40 80,   443 20d

alahijani avatar May 18 '18 20:05 alahijani

The b option is included for convenience but in fact violates Unix philosophy. You can get a similar result by piping q output through column -t, so it's not strictly needed. Therefore I think adding another option on the input side would be a step in the wrong direction. Instead I suggest making an input transformation to distinguish between column separators and literal spaces:

kubectl get ingress | sed 's/  \+/\t/g' | q -tHOb 'select * from -'

Or instead of -b use the suggested column command:

kubectl get ingress | sed 's/  \+/\t/g' | q -tHO 'select * from -' | column -t -s$'\t'

This also leads to a slightly different spacing (which might be preferable).

bitti avatar May 18 '18 21:05 bitti

While I understand the issue with kubectl's output, I agree with @bitti on this. Adding such a capability to q would be cumbersome, probably error prone, and a step in the wrong direction. kubectl effectively has a bug in its output, since it does provide multiple output formats, but doesn't fully provide a table format that is machine-parsable.

I would take another approach and create a more generic preprocessing capability that converts the visual table structure to a more logical one.

Here's a short script I've written to convert visual-space-delimited fields into logical ones. It uses the header row as a hint on how to split the other rows. You can use it as follows (notice that i've added the -d , since i've made the csv-size script hardcoded to create comma separated fields).

kubectl get ingress | ./csv-ize | q -HOb -d , 'select * from -'

Below is the code for csv-ize. Obviously it could benefit from parameterizing some stuff and making it more robust to errors.

#!/usr/bin/env python

import os,sys
import re
import csv

w = csv.writer(sys.stdout,delimiter=',',quotechar='"',quoting=csv.QUOTE_ALL)

h = sys.stdin.readline()[:-1]
positions = [0] + [x.start()+1 for x in re.finditer(' [^ ]',h)] + [len(h)]

def split_line(l,positions,trim=True):
    do_format = lambda v: v.strip() if trim else v
    return [do_format(l[p0:p1]) for p0,p1 in zip(positions,positions[1:])]

header = split_line(h,positions)
w.writerow(header)

line = sys.stdin.readline()
while line:
    line = line[:-1]

    w.writerow(split_line(line,positions))

    line = sys.stdin.readline()

harelba avatar Jul 07 '18 10:07 harelba