4

I have a file containing lists on Solaris:

List A
hi
hello
hw r u

List B
Hi
Yes

List C
Hello

I need to transpose the lists as shown below:

List A    List B    List C
hi        Hi        Hello
hello     Yes
hw r u

How can I do this on Solaris?

αғsнιη
  • 41,407
John
  • 51

4 Answers4

3

You could use awk to split each block into separate files, then paste them together (below is assuming always there is empty lines between each lists).

awk '/^$/ {N++;next}{print >"file"N}' infile.txt
paste file*

Also you can move the paste command into awk.

awk '/^$/ {N++;next}{print >"file"N} END{system("paste file*")}' inile.txt

The output is:

List A    List B    List C
hi        Hi        Hello
hello     Yes
hw r u

to having beauty indentation in result when varying lines length like below:

Input file:

list A
hi
hello
hw r u

List B Hi this is list B Yes

List C Hello, this is list C

you can do paste file* |column -s $'\t' -tn and will have result:

list A  List B             List C
hi      Hi this is list B  Hello, this is list C
hello   Yes
hw r u
αғsнιη
  • 41,407
  • Instead of awk, csplit might be more suitable as it is designed for file splitting on a pattern match. In this case match empty lines and delete the match pattern: csplit -f file_ --suppress-matched infile.txt '/^$/' '{*}' . ALSO: Note that the pasting via paste file* might be problematic when having file1 and file10. – FelixJN Sep 18 '20 at 08:17
1

Besides of my previous answer, there is also csplit command to split the file in that same way and then use paste command to get desired output.

csplit -zs -f outputfile inputfile '/^List/' '{*}'
paste outfile*
  • '/^List/' is a pattern to match and break the file there into the next new file
  • '{*}' repeat the pattern as many times as possible
  • -z is used to remove empty output files; and -s is used to do not print counts of output file sizes
  • -f is used to define custom prefix outputfile## where ## is by default 2 digits, you can define it with -n N (N is number of digits in suffix after defined prefix)
αғsнιη
  • 41,407
0

GNU awk approach:

awk 'BEGIN{ max=0 }
     /^List/{ if(k && k>max) { max=k; idx=c } ++c; k=0 }
     NF{ a[c][++k]=$0 }
     END{ 
         for(i=1;i<=max;i++) 
             for(j=1;j<=c;j++) printf "%s%s",a[j][i],(j==c)?ORS:"\t" 
     }' file | column -ts$'\t'

The output:

List A  List B  List C
hi      Hi      Hello
hello   Yes
hw r u
0

Command

for i in "List A" "List B" "List C"; do sed -n "/$i/,/^$/p" h.txt >"$i.txt"; done

paste List\ *

output

List A  List B  List C
hi  Hi  Hello
hello   Yes 
hw r u