LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-28-2014, 10:09 PM   #1
sharky
Member
 
Registered: Oct 2002
Posts: 569

Rep: Reputation: 84
Convert lines to columns


I am betting there is a simple awk one liner that will do what I need. However, I haven't found it yet.

What I need is very simple. I want to take a mult-line input and convert to columns for each nth line.

Example: say n is 3 and the input is;

Quote:
some - text
more - text
even - more
yet - again
for - ever
stop - now
What I want returned is;

Quote:
some - text yet - again
more - text for - ever
even - more stop - now
Nothing more complicated than that. No special cases. Just convert n number of lines into columns with each column seperated by a space.

I guess there is one additional complication; In the example above if the number of lines on the input were 9 instead of 6 I would get 3 columns returned instead of two.

It is OK if the n is hard coded. As a matter of fact it's preferable.

I'm still digging so if I find a solution I will be sure to post it.

Cheers,

Last edited by sharky; 06-29-2014 at 12:52 AM.
 
Old 06-28-2014, 11:05 PM   #2
BenCollver
Rogue Class
 
Registered: Sep 2006
Location: OR, USA
Distribution: Slackware64-15.0
Posts: 375
Blog Entries: 2

Rep: Reputation: 172Reputation: 172
Post

It may not be elegant, but below is a working script. example: ./test.sh input.txt 3

Code:
#!/bin/sh
fn="$1"
n="$2"
if [ ! -f "$fn" -o -z "$n" -o "$n" -lt 2 ]
then
    echo "Usage: test.sh filename lines"
fi
for i in $(seq 1 $n)
do
    tail -n +$i "$fn" | awk "NR == 1 || NR % $n == 0" | tr '\n' ' '
    echo ""
done
exit 0
 
Old 06-29-2014, 12:33 AM   #3
sharky
Member
 
Registered: Oct 2002
Posts: 569

Original Poster
Rep: Reputation: 84
That was close but not quite.

I created a test file that was 27 lines. The test file simply list 1 - 9 three times.
Quote:
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
The output from your script was this;

Quote:
1 9 9 9
2 1 1
3 2 2
4 3 3
5 4 4
6 5 5
7 6 6
8 7 7
9 8 8
Not sure how to fix it but it's definitely close.

Thanks for the help.
 
Old 06-29-2014, 01:54 AM   #4
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Well this looks a little clumsy but you get the idea:
Code:
awk '{a=NR%3?NR%3:3;b[a]=b[a](b[a]?" ":"")$0}END{for(i=1;i<=3;i++)print b[i]}' file
 
Old 06-29-2014, 02:02 AM   #5
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,126

Rep: Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120
Quote:
Originally Posted by grail View Post
... but you get the idea:
Luv it - how to make awk look like perl ....
 
Old 06-29-2014, 06:56 AM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Using pr:

Code:
pr -t -s' ' --columns=$(($(wc -l < input) / 3)) input
Unfortunately, it needs to get the input twice.

@grail: you can simplify a bit by using 0 based indexing:
Code:
awk '{a=(NR-1)%3;b[a]=b[a](b[a]?" ":"")$0}END{for(i=0;i<3;i++)print b[i]}' file
 
1 members found this post helpful.
Old 06-29-2014, 07:14 AM   #7
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Cheers ntubski I have a cold and I knew there was a way but the head was not playing the game
 
Old 06-29-2014, 07:35 AM   #8
BenCollver
Rogue Class
 
Registered: Sep 2006
Location: OR, USA
Distribution: Slackware64-15.0
Posts: 375
Blog Entries: 2

Rep: Reputation: 172Reputation: 172
Ah, the script was off by one.

OLD: NR % $n
NEW: (NR-1) % $n

Code:
#!/bin/sh
fn="$1"
n="$2"
if [ ! -f "$fn" -o -z "$n" -o "$n" -lt 2 ]
then
    echo "Usage: test.sh filename lines"
fi
for i in $(seq 1 $n)
do
    tail -n +$i "$fn" | awk "NR == 1 || (NR-1) % $n == 0" | tr '\n' ' '
    echo ""
done
exit 0

Last edited by BenCollver; 06-29-2014 at 07:35 AM. Reason: correction
 
Old 06-29-2014, 12:44 PM   #9
sharky
Member
 
Registered: Oct 2002
Posts: 569

Original Poster
Rep: Reputation: 84
Several solutions that work!

Thanks to everyone.
 
Old 06-29-2014, 07:36 PM   #10
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
For your consideration: a different approach.

Advantage: simple code
Disadvantage: uses work files

With this InFile ...
Code:
some - text
more - text
even - more
yet - again
for - ever
stop - now
... this code ...
Code:
rm $Work*; split -dl3 $InFile $Work; paste $Work* >$OutFile
... produced this OutFile ...
Code:
some - text	yet - again
more - text	for - ever
even - more	stop - now
With this InFile ...
Code:
some - text
more - text
even - more
yet - again
for - ever
stop - notyet
apple - fruit
honda - car
purple - color
... the same code produced this OutFile ...
Code:
some - text	yet - again	apple - fruit
more - text	for - ever	honda - car
even - more	stop - notyet	purple - color
Daniel B. Martin
 
1 members found this post helpful.
Old 08-03-2021, 11:06 AM   #11
shruggy
Senior Member
 
Registered: Mar 2020
Posts: 3,670

Rep: Reputation: Disabled
Just for fun, building upon Daniel's idea
Code:
#/bin/bash
input=$(seq -w 12)

# split in three, then paste each part sequentially
echo == 1 ==
<<<"$input" split -nr/3 --filter='paste -sd\ '
echo == 2 ==
getrow(){<<<"$input" split -nr/$1/3;}
paste -sd' ' <(getrow 1) <(getrow 2) <(getrow 3)

# paste three in parallel, then transpose
xpos=$(<<<"$input" paste - - -)
echo == 3 ==
getcol(){<<<"$xpos" cut -f$1;}
paste -sd' ' <(getcol 1) <(getcol 2) <(getcol 3)
echo == 4 ==
for i in 1 2 3;do <<<"$xpos" cut -f$i|paste -sd' ';done
echo == 5 ==
csvtool -t TAB -u ' ' transpose - <<<"$xpos"
echo == 6 ==
csvtk -tD' ' transpose <<<"$xpos"
The tools used in the last two solutions are csvtool and csvtk.

Last edited by shruggy; 08-05-2021 at 03:19 AM.
 
Old 08-03-2021, 04:44 PM   #12
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,126

Rep: Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120
I wonder if anyone (else) still cares all these years later ...
 
Old 08-03-2021, 11:35 PM   #13
rnturn
Senior Member
 
Registered: Jan 2003
Location: Illinois (SW Chicago 'burbs)
Distribution: openSUSE, Raspbian, Slackware. Previous: MacOS, Red Hat, Coherent, Consensys SVR4.2, Tru64, Solaris
Posts: 2,800

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
Quote:
Originally Posted by syg00 View Post
Luv it - how to make awk look like perl ....
IMHO, only bonkers Perl programmers write code like that.

(I'm working on a project that uses a large number of Perl modules -- surely totaling well over 10,000 lines of code -- and none of what I've seen of the code base looks like that.)
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] How to convert the rows of data into the columns? w1k0 Programming 101 02-06-2014 09:24 PM
[SOLVED] bash suggestions to convert horizontal columns to vertical columns Guyverix Programming 14 01-24-2013 11:03 AM
[SOLVED] Converting columns to lines using AWK bldcerealkiller Programming 10 11-04-2011 02:02 PM
How many lines and columns in a 17" monitor macondo Linux - Hardware 1 11-04-2004 06:00 PM
columns to lines Luskacik Linux - General 2 08-31-2004 11:38 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:27 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration