How to convert a single column into several columns?

Hi

I have a ksh script which gives me the output as a single column with several rows like:

AAA
BBB
CCC
DDD
EEE
FFF
GGG
HHH
III

I want to be able to create a new file from this file which allows me to set the number of rows and columns in the new file, i.e. for this example, if I specify 3 rows and 3 columns, the output should look like

file.txt:

AAA DDD GGG
BBB EEE HHH
CCC FFF III

Is it possible to do this in Unix using sed command and in comma separated?

I tried

cat file.txt | sed 'N;N;s/\n/,/g'

but its giving me wrong output.

Thank You,
Pinpe

Try this.

cgi@tioman> (/home/cgi) $ awk -v col=3 '{if(NR%col){printf "%s ",$0 }else {printf "%s\n",$0}} ' test.txt
AA BBB CCC
DDD EEE FFF
GGG HHH III
cgi@tioman> (/home/cgi) $

But i think you can set any one rows / columns and the other goes depends on your file size.

perl -0ane 'BEGIN{$cols=3}END{for($i=0;$i<=$#F;$i++){print "$F[$i]\t"; print "\n" if((($i+1) % $cols) == 0)}}' inp

Her I have given the cols a 3. You can change it as per ur req

Hi getmmg/kumaran_5555,

Thanks for the prompt response but..

My desired output should be like this...

AAA DDD GGG
BBB EEE HHH
CCC FFF III

Your script output is this...

AAA BBB CCC
DDD EEE FFF
GGG HHH III

Br,
Pete

Using Awk

awk '{A[(NR-1)%3]=A[(NR-1)%3]$0" ";next}END{for(i in A)print A}' your_infile

We all missed that. :slight_smile:
Try this one, again you have freedom to choose only the rows. This works on linux.

cgi@tioman> (/home/cgi) $ awk -v row=3 '{arr[NR%row]=arr[NR%row]" "$0} END{n=asort(arr);for(i=1;i<=n;i++){print arr}} ' test.txt
 AA DDD GGG
 BBB EEE HHH
 CCC FFF III

This should work

perl -lne 'BEGIN{$cols=3;$i=0}; $hash{$i}.= "$_ "; $i++; $i=0 if($i == $cols); END{print $_ for values %hash}' inp

how does awk ensures the array's index order. Usually it has arbitrary order, an you may end up with different line order in the output.

Hi getmmg,

Still does not work for my desired output. Let me clear my input and outful files as shown below...

inputfile.txt:


AAA
BBB
CCC
DDD
EEE
FFF
GGG
HHH
III
JJJ
KKK
LLL
MMM
NNN
OOO

output.txt file is like this...


AAA     FFF     KKK
BBB     GGG     LLL
CCC     HHH     MMM
DDD     III     NNN
EEE     JJJ     OOO

Thanks in advance.

Br,
Pinpe

Have you tried my command,

it worked fine.

cgi@tioman> (/home/cgi) $ awk -v row=5 '{arr[NR%row]=arr[NR%row]" "$0} END{n=asort(arr);for(i=1;i<=n;i++){print arr}} ' test.txt
 AAA FFF KKK
 BBB GGG LLL
 CCC HHH MMM
 DDD III NNN
 EEE JJJ OOO

Hi kumaran_5555,

I'm getting error...

root@pinpe>awk -v row=5 '{arr[NR%row]=arr[NR%row]" "$0} END{n=asort(arr);for(i=1;i<=n;i++){print arr}}' inputfile.txt
awk: syntax error near line 1
awk: bailing out near line 1

Thanks.

Br,
Pinpe

Hi Pinpe,

if you are using solaris...please use nawk instead of awk as Kumaran has mentioned he tried in Linux.

Thanks
Sha

Hi getmmg,

This one works for me but it somehow re-arranged the position of the values. My inputfile is actually a list of numbers and not letters. Can you please modify a little this code of yours? Thanks.

389    
57     
4      
29     
51     
382    
527    
10625  
87868  
18     
5      
1807367
8614   
730    
7025   

The output should be like this...

389     382       5      
57      527       1807367
4       10625     8614   
29      87868     730    
51      18        7025   

Thanks in advance.

Br,
Pinpe

Pinpe,

This should work

 
 
perl -0ane 'BEGIN{$cols=5;$k=0}END{$total=($#F+1)/$cols;foreach(@F){$hash{$k}.= "$_\t";$k++; $k=0 if($k == $total)}; print "$_\n" for values %hash}' inp
 

I've got following output when the cols was given as 5 and then as 3.
Let me know if this is what you require.

Output I got

 
 
5 cols
 
AAA DDD GGG JJJ MMM
BBB EEE HHH KKK NNN
CCC FFF III LLL OOO
 
3 cols
 
AAA FFF KKK
BBB GGG LLL
CCC HHH MMM
DDD III NNN
EEE JJJ OOO

Hi getmmg,

Can you please use the input file below. So instead of letter you will use numbers.

389    
57     
4      
29     
51     
382    
527    
10625  
87868  
18     
5      
1807367
8614   
730    
7025   

The output should be like this...

389     382       5      
57      527       1807367
4       10625     8614   
29      87868     730    
51      18        7025   

Thanks in advance.

Br,
Pinpe

This is what I've got

 
389     382     5
57      527     1807367
4       10625   8614
29      87868   730
51      18      7025

Hi getmmg,

What do you think its giving me a wrong output...?

root@pinpe>perl -0ane 'BEGIN{$cols=3;$k=0}END{$total=($#F+1)/$cols;foreach(@F){$hash{$k}.= "$_\t";$k++; $k=0 if($k == $total)}; print "$_\n" for values %hash}' test.txt 
51      18      7025    
57      527     1807367 
29      87868   730     
389     382     5       
4       10625   8614

Thanks,
Pete

gawk -v row=3 '{arr[NR%row]=arr[NR%row]" "$0} END{n=asort(arr);for(i=1;i<=n;i++){print arr}} ' test.txt

Try this one with gawk/nawk, this should work

Hello Pinpe,

I guess it's giving the output properly ( order is missing ) . Check it out how to get the output in the order you read!!!

Regards
Ravi