~spidernet/tabular

Command line utility that reads files containing tabular data sequentially and pretty prints them as a table.
~spidernet/tabular-dev

New mailing list added

2 days ago

966b295 Merge branch 'master' of git.sr.ht:~spidernet/tabular

11 days ago

#tabular

The tabular utility reads files containing tabular data sequentially and pretty prints them as a table. The file operands are processed in command-line order. If the file is a single dash (‘-’) or absent, tabular reads from the standard input. The separator character(s) of each column in the data set can be specified at run-time, which defaults to ','.

#Features

  • Quality
    • Compiled with security hardening flags.
    • Static analysis integrated using clang's scan-build using checkers alpha.security, alpha.core.CastSize, alpha.core.CastToStruct, alpha.core.IdenticalExpr, alpha.core.PointerArithm, alpha.core.PointerSub, alpha.core.SizeofPtr, alpha.core.TestAfterDivZero, alpha.unix.
    • Follows FreeBSD coding style.
    • RFC4180 compliant:
      • handles \n, \r and \r\n as new line
      • if double-quotes are used to enclose fields it handles double quotes appearing inside a field only if escaped by preceding it with another double quote. For example "x""y" is equivalent to x"y
      • handles the precence of the separator character inside a quoted field.
  • Portable
    • C99 compliant and may be built in an environment which provides POSIX.1-2001 system interfaces.
    • Self-contained, no external dependencies
    • Easy to compile and uses POSIX make.

#Limitations

  • Input lines are limited to LINE_MAX bytes in lenght.
  • Only single character separators are allowed for now.
  • The program presumes the locale is UTF-8.

#Build dependencies

The only dependency is a toolchain supporting the following flags:

CFLAGS = -std=c99 -O2 -Wall -Wextra -Wpedantic \
	-Walloca -Wcast-qual -Wconversion -Wformat=2 -Wformat-security \
	-Wnull-dereference -Wstack-protector -Wvla -Warray-bounds \
	-Wbad-function-cast -Wconversion -Wshadow -Wstrict-overflow=4 -Wundef \
	-Wstrict-prototypes -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough \
	-Wpointer-arith -Wswitch-enum \
	-D_FORTIFY_SOURCE=2 \
	-fstack-protector-strong -fPIE -fstack-clash-protection

LDFLAGS = -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-z,separate-code

Otherwise you can just remove the security flags and compile it with

CFLAGS = -std=c99 -O2 -Wall -Wextra -Wpedantic
LDFLAGS =

or pass your own flags to make

make CC=gcc CFLAGS=... LDFLAGS=...

#Installation

Clone this repository then

$ make PREFIX=/usr install

This will install the compiled binary under PREFIX (/usr/bin) in this case, if not specified PREFIX will default to /usr/local. For staged installs, DESTDIR is also supported. As the binary does not have any dependency it does not have to be installed before use.

#Usage

tabular receives as input one or more files to print as a table. The files however, can be omitted, in this case the program takes the input from the standard input until EOF or ^D is reached. If a file is a single dash (‘-’), tabular reads from standard input.

The options are as follows:

  • -s Specify a character to be used to delimit the columns and each field. If omitted ',' is used.

#Examples

Example CSVs are taken from https://people.sc.fsu.edu/~jburkardt/data/csv/csv.html

$ cat addresses.csv
John,Doe,120 jefferson st.,Riverside, NJ, 08075
Jack,McGinnis,220 hobo Av.,Phila, PA,09119
"John ""Da Man""",Repici,120 Jefferson St.,Riverside, NJ,08075
Stephen,Tyler,"7452 Terrace ""At the Plaza"" road",SomeTown,SD, 91234
,Blankman,,SomeTown, SD, 00298
"Joan ""the bone"", Anne",Jet,"9th, at Terrace plc",Desert City,CO,00123

$ tabular addresses.csv
John                   Doe       120 jefferson st.                 Riverside     NJ   08075
Jack                   McGinnis  220 hobo Av.                      Phila         PA  09119
John "Da Man"          Repici    120 Jefferson St.                 Riverside     NJ  08075
Stephen                Tyler     7452 Terrace "At the Plaza" road  SomeTown     SD    91234
                       Blankman                                    SomeTown      SD   00298
Joan "the bone", Anne  Jet       9th, at Terrace plc               Desert City  CO   00123
$ tabular tally_cab.csv - addresses.csv <<EOF
foo,bar,baz
a,b,c,
EOF

Distance (miles)   "Fare ($)"
 4.5                 18.00
26.7                 73.75
 6.7                 23.00
16.4                 56.00
32.7                 83.25
 5.7                 17.50
77.0                190.50
 8.3                 19.65
foo  bar  baz
a    b    c
John                   Doe       120 jefferson st.                 Riverside     NJ   08075
Jack                   McGinnis  220 hobo Av.                      Phila         PA  09119
John "Da Man"          Repici    120 Jefferson St.                 Riverside     NJ  08075
Stephen                Tyler     7452 Terrace "At the Plaza" road  SomeTown     SD    91234
                       Blankman                                    SomeTown      SD   00298
Joan "the bone", Anne  Jet       9th, at Terrace plc               Desert City  CO   00123
$ cat names.csv | tabular -s ';'
ID     NAME                  AGE
23434  Norris, Chuck         24
34343  Bond, James "master"  57

#Static analysis

Static analysis on the code base is done by using clang's static analyzer run through scan-build.sh which wraps the scan-build utility. The checkers used are part of the Experimental Checkers (aka alpha checkers):

  • alpha.security
  • alpha.core.CastSize
  • alpha.core.CastToStruct
  • alpha.core.IdenticalExpr
  • alpha.core.PointerArithm
  • alpha.core.PointerSub
  • alpha.core.SizeofPtr
  • alpha.core.TestAfterDivZero
  • alpha.unix