Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output a file in two columns in BASH

Tags:

bash

I'd like to rearrange a file in two columns after the nth line.

For example, say I have a file like this here:

This is a bunch
of text
that I'd like to print
as two
columns starting
at line number 7
and separated by four spaces.
Here are some
more lines so I can
demonstrate
what I'm talking about.

And I'd like to print it out like this:

This is a bunch           and separated by four spaces.
of text                   Here are some
that I'd like to print    more lines so I can
as two                    demonstrate
columns starting          what I'm talking about.
at line number 7

How could I do that with a bash command or function?

like image 562
user3435529 Avatar asked Sep 17 '25 09:09

user3435529


2 Answers

Actually, pr can do almost exactly this:

pr --output-tabs=' 1' -2 -t tmp1 

This is a bunch                     and separated by four spaces.
of text                             Here are some
that I'd like to print              more lines so I can
as two                              demonstrate
columns starting                    what I'm talking about.
at line number 7  

-2 for two columns; -t to omit page headers; and without the --output-tabs=' 1', it'll insert a tab for every 8 spaces it added. You can also set the page width and length (if your actual files are much longer than 100 lines); check out man pr for some options.

If you're fixed upon “four spaces more than the longest line on the left,” then perhaps you might have to use something a bit more complex;

The following works with your test input, but is getting to the point where the correct answer would be, “just use Perl, already;”

#!/bin/sh
infile=${1:-tmp1}
longest=$(longest=0;
          head -n $(( $( wc -l $infile | cut -d ' ' -f 1 ) / 2 )) $infile | \
              while read line
              do
                  current="$( echo $line | wc -c | cut -d ' ' -f 1 )"
                  if [ $current -gt $longest ]
                  then
                      echo $current
                      longest=$current
                  fi
              done | tail -n 1 )
pr -t -2 -w$(( $longest * 2 + 6 )) --output-tabs=' 1' $infile

This is a bunch           and separated by four spa
of text                   Here are some
that I'd like to print    more lines so I can
as two                    demonstrate
columns starting          what I'm talking about.
at line number 7          

… re-reading your question, I wonder if you meant that you were going to literally specify the nth line to the program, in which case, neither of the above will work unless that line happens to be halfway down.

like image 196
BRPocock Avatar answered Sep 19 '25 08:09

BRPocock


Thank you chatraed and BRPocock (and your colleague). Your answers helped me think up this solution, which answers my need.

function make_cols
{
     file=$1         # input file
     line=$2         # line to break at
     pad=$(($3-1))   # spaces between cols - 1

     len=$( wc -l < $file )
     max=$(( $( wc -L < <(head -$(( line - 1 )) $file ) ) + $pad ))

     SAVEIFS=$IFS;IFS=$(echo -en "\n\b")

     paste -d" " <( for l in $( cat <(head -$(( line - 1 )) $file ) )
           do
                printf "%-""$max""s\n" $l
           done ) \
           <(tail -$(( len - line + 1 )) $file )

     IFS=$SAVEIFS
}

make_cols tmp1 7 4
like image 40
user3435529 Avatar answered Sep 19 '25 07:09

user3435529