This seems like a simple task, but using duckduckgo I wasn't able to find a way to properly do what I'm trying to.
The main question is: How do I split the output of a command in linux or bash into multiple columns using a delimeter?
I have a file that looks like this: (this is just a simplified example)
-----------------------------------
Some data
that varies in line length
-----------------------------------
-----------------------------------
More data that is seperated
by a new line and dashes
-----------------------------------
And so on. Everytime data gets written to the file, it's enclosed in a line of dashes, seperated by an empty line from the last block. Line-length of the data varies. What I want is basically a tool or way using bash to split the file into multiple columns like this:
----------------------------------- -----------------------------------
Some data More data that is seperated
that varies in line length by a new line and dashes
----------------------------------- -----------------------------------
Each column should take 50% of the screen, no centering (as in alignment) needed. The file has to be split per-block. Splitting the file in the middle or something like that won't work. I basically want block 1 go to the left column, block 2 to the right, 3 to the left again, 4 right, and so on. The file gets updated constantly and updates should be written to the screen right away. (Currently I'm using tail -f
)
Since this sounds like a rather common question I would welcome a general approach to this instead of a specific answer that works only for my case so people coming from search engines looking for a way to have a two column layout in bash get some information too. I tried column
and pr
, both don't work as desired. (I elaborated on this in the comments)
Edit: To be clear, I am looking for a general approach on this. Going through a file, getting data between the delimiter, putting it to column A, getting the next one putting it to column B, and so on.
Assuming file contains uniform blocks of five lines each, using
paste
,sed
, andprintf
:Problem with OP spec
The OP reports that the block lengths may vary, and should be separated by a fixed number of lines. Even numbered blocks go in Column A, odd numbered blocks in Column B.
That creates a
tail -f
problem then. Suppose the block lengths of the source input begin with 1000 lines, then one line, 1000, 1, 1000, 1, etc. So Column A gets all the 1000 line blocks, and Column B gets all the one line blocks. Let's say the blocks in the output are separated by 1 line each. So one block in Column A lines up with 500 blocks in Column B. So for a terminal with scrolling output, that means before we can output the first block in Column A, we have to wait for 1000 blocks of input. To output the third block in Column A, (just below the first block), we have to wait for 2000 blocks of input.If the blocks are added to the input file relatively slowly, with a one second delay between blocks, then it will take three seconds for the block 3 to appear in the input file, but it will take 33 minutes for block 3 to be displayed in the output file.
This script is getting max width of current terminal and splitting it in 2, then printing records split by RS="\n\n" separator, print the first found and placing the cursor at the first line/last column of it to write the next record.
Here's a simpler version
Output
The question is tagged as Perl so here is a possible Perl answer:
Output:
Alright, since apprently there is no clean way to do this I came up with my own solution. It's a bit messy and requires GNU
screen
to be installed, but it works. Any amount of lines within or around the blocks, 50% of the screen automatically resizing and each column prints independantly from each other with a fixed amount of newlines between them. Also automatic updates every x seconds. (120 in my example)First, start a screen session with
screen -S testscr
then, either within or outside the session, execute the script above. This will split the screen vertically using 50% per column and executetail -f
on both columns, afterwards it will go through the input file and write block by block to each tmp. file in the desired way. Since it's in an infinite while loop it's essentially automatically updating the shown output every x seconds (here120
).