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нιη
  • 40,939
  • 15
  • 71
  • 114
John
  • 51
  • 4

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нιη
  • 40,939
  • 15
  • 71
  • 114
  • 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нιη
  • 40,939
  • 15
  • 71
  • 114
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
RomanPerekhrest
  • 29,703
  • 3
  • 43
  • 67
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      
Praveen Kumar BS
  • 5,139
  • 2
  • 9
  • 14