Using the column command

The column command is extremely useful for formatting tabular data.
We will cover a number of useful examples such as pretty printing tables to dealing with CSV and JSON.

  1. Version of "column" utility
  2. Basic use
  3. Naming the columns
  4. Printing with the columns arranged in a different order
  5. Printing with certain columns removed
  6. Printing a JSON representation
  7. Setting a custom input delimiter/separator
  8. Setting a custom output separator

The column utility is provided by the util-linux package.
I'm using Fedora 26 with util-linux 2.30.2.
On older systems, many of the features in this tutorial won't work

Let's look at some simple examples using the following input

$ ip -4 -brief address show
lo               UNKNOWN        127.0.0.1/8 
ens33            UP             10.10.0.129/24 
ens37            UP             192.168.122.128/24 
dummy0           UNKNOWN        172.16.32.64/32 

We can use column -t to tabulate it.
It looks mostly the same except it's slightly compacted.

$ ip -4 -brief address show | column -t
lo      UNKNOWN  127.0.0.1/8
ens33   UP       10.10.0.129/24
ens37   UP       192.168.122.128/24
dummy0  UNKNOWN  172.16.32.64/32

Let's define the names of each column. We use column -tN "n1,n2,n3"

$ ip -4 -brief address show | column -tN "dev,state,inet"
dev     state    inet
lo      UNKNOWN  127.0.0.1/8
ens33   UP       10.10.0.129/24
ens37   UP       192.168.122.128/24
dummy0  UNKNOWN  172.16.32.64/32

Let's rearrange the order of the columns We do this with -O

$ ip -4 -brief address show | column -tN "dev,state,inet" -O "inet,dev,state"
inet                dev     state
127.0.0.1/8         lo      UNKNOWN
10.10.0.129/24      ens33   UP
192.168.122.128/24  ens37   UP
172.16.32.64/32     dummy0  UNKNOWN

What if we want to remove a particular column from our printout We do this with -H ``` $ ip -4 -brief address show | column -tN "dev,state,inet" -H "state" dev inet lo 127.0.0.1/8 ens33 10.10.0.129/24 ens37 192.168.122.128/24 dummy0 172.16.32.64/32 ```

Want JSON? To do this, we simply use -tJN

$ ip -4 -brief address show | column -tJN "dev,state,inet"
{
   "table": [
      {"dev": "lo", "state": "UNKNOWN", "inet": "127.0.0.1/8"},
      {"dev": "ens33", "state": "UP", "inet": "10.10.0.129/24"},
      {"dev": "ens37", "state": "UP", "inet": "192.168.122.128/24"},
      {"dev": "dummy0", "state": "UNKNOWN", "inet": "172.16.32.64/32"}
   ]
}

By default, the json object will be named "table"
We can set the name by putting --table-name at the end of the command.

What about pretty-printing?,
We need to install jq

$ ip -4 -brief address show | column -tJN "dev,state,inet" --table-name "ipconfig" | jq
{
  "ipconfig": [
    {
      "dev": "lo",
      "state": "UNKNOWN",
      "inet": "127.0.0.1/8"
    },
    {
      "dev": "ens33",
      "state": "UP",
      "inet": "10.10.0.129/24"
    },
    {
      "dev": "ens37",
      "state": "UP",
      "inet": "192.168.122.128/24"
    },
    {
      "dev": "dummy0",
      "state": "UNKNOWN",
      "inet": "172.16.32.64/32"
    }
  ]
}

What if we need to read CSVs or anything else that isn't delimited with whitespace? We can read input delimited by an arbitrary string, set with -s

column -ts"," -N "dev,state,inet" < example.csv 
dev     state    inet
lo      UNKNOWN  127.0.0.1/8
ens33   UP       10.10.0.129/24
ens37   UP       192.168.122.128/24
dummy0  UNKNOWN  172.16.32.64/32

What about setting an arbitrary string to separate columns on the printout? We use --output-separator=

$ column -ts"," -N "dev,state,inet" --output-separator="  |  " <example.csv
dev     |  state    |  inet
lo      |  UNKNOWN  |  127.0.0.1/8
ens33   |  UP       |  10.10.0.129/24
ens37   |  UP       |  192.168.122.128/24
dummy0  |  UNKNOWN  |  172.16.32.64/32
[root@PC ~]#