Bash - Adding titles into to a piped table command

2019-08-01 16:45发布

问题:

I have a simple script to output the content of the file students.txt as a basic table to the print file, which is then displayed.

#!/bin/bash

cat students.txt | column -t -s',' | sort -u -k3 > print.txt
cat print.txt

The output looks like as follows:

Consoling  ST  DWC  0900
Scribing   RA  DWC  1000
Gloater    AU  DWC  1100
Crimp      DI  DWC  1200

and so on. However I also want to be able to add headings for each column and have them align perfectly, as well as not being sorted. I have tried to use printf and echo but when piped into the command they do not display and I cannot align the columns correctly by printing the heading names outside of the pipe. The desired output I am looking for would look like this:

Family Name  Initials  Interviewer Initials  Interview Time
Consoling    ST        DWC                   0900
Scribing     RA        DWC                   1000
Gloater      AU        DWC                   1100
Crimp        DI        DWC                   1200

How could I achieve this?

回答1:

There is a oneliner:

cat <(echo "Family Name,Initials,Interviewer Initials,Interview Time") <(sort -u -k3 -t ',' students.txt) | column -s ',' -t > print.txt

This makes use of Process Substitution. The command inside <() is run and it's output appears as a filename. cat concatenates the two "files", that contain the outputs of echo (for the headers) and sort (to sort your students.txt).

  • sort is run with option -t ',' to specifiy "," as the delimiter.
  • column is run with option -s ',' to specify "," as the delimiter.

EDIT (thanks to @tripleee for pointing it out):

The oneliner can be modified, such that Process Substitution and cat isn't necessary:

{ echo "Family Name,Initials,Interviewer Initials,Interview Time"; sort -u -k3 -t ',' students.txt; } | column -s ',' -t > print.txt

echo and sort are grouped by {} and are executed in the current shell context. The redirection (pipe to column) is applied to the entire group. For reference: Grouping Commands.



回答2:

May be you can try a simple echo

cat students.txt | column -t -s',' | sort -u -k3 > print.txt
echo 'Family Name  Initials  Interviewer Initials  Interview Time' && cat print.txt

If you need them to be aligned based on your headings then you can use column

column -t <<< "Family_Name  Initials  Interviewer_Initials  Interview_Time
Consoling  ST  DWC  0900
Scribing   RA  DWC  1000
Gloater    AU  DWC  1100
Crimp      DI  DWC  1200
"
Family_Name  Initials  Interviewer_Initials  Interview_Time
Consoling    ST        DWC                   0900
Scribing     RA        DWC                   1000
Gloater      AU        DWC                   1100
Crimp        DI        DWC                   1200

Note: spaces in column header is not allowed, else it would be treated as separate columns



回答3:

You put the header Family Name, Initials, Interviewer Initials, Interview Time before the contents of students.txt before sending it to the column comand, and I think that should do the trick.

Perhaps something like:

TEMP=$(mktemp)
TEMP2=$(mktemp)
cat students.txt | sort -u -k3 > $TEMP
echo Family Name, Initials, Interviewer Initials, Interview Time > $TEMP2
cat $TEMP >> $TEMP2
cat $TEMP2 | column -t -s',' > print.txt
rm -f $TEMP $TEMP2
cat print.txt


标签: bash pipe