Robert
Robert

Reputation: 19

Convert rows to columns with bash

I have a large text file that looks like the example below. It has many more groups of rows seperated by an empty row.

Aggr2_N1_SATA
Normal
192.168.1.2:/floluesxprd5_ds_vol1
Unknown
522.50 GB
478.69 GB
NFS
10/14/2020 3:21:52 PM
Enabled
Disabled
Not supported

boot_lun_svr1
Normal
NETAPP Fibre Channel Disk (naa.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx):3
Non-SSD
5.00 GB
4.29 GB
VMFS5
2/10/2020 4:26:37 PM
Enabled
Disabled
Supported

I would like to convert it to look like this:

Aggr2_N1_SATA,Normal,192.168.1.2:/floluesxprd5_ds_vol1,Unknown,522.50 GB,478.69 GB,NFS,10/14/2020,3:21:52 PM,Enabled,Disabled,Not supported

boot_lun_svr1,Normal,NETAPP Fibre Channel Disk (naa.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx):3,Non-SSD,5.00 GB,4.29 GB,VMFS5,2/10/2020 4:26:37 PM,Enabled,Disabled,Supported

Any ideas are appreciated!

Upvotes: 1

Views: 8359

Answers (6)

jaypal singh
jaypal singh

Reputation: 77095

Here is a way using GNU sed to complete the rout. Please note that this is only for reference and you are better off using glenn jackman's perl solution as that is portable and easy to understand.

Easy way is to read the entire file in one long string separated by , and then putting newlines when two consecutive , are seen.

sed '
    :a;            # Create a label a for a loop
    $!N;           # Append the next line to pattern space if it is not the last line
    s/\n/,/;       # Substitute the newline with ,
    ta;            # If the substitution modified pattern space repeat the loop
    s/,,/\n\n/g    # At the end, substitute two , with two newlines
' file

One-liner form:

sed ':a;$!N;s/\n/,/;ta;s/,,/\n\n/g' file

However, reading entire file in one long string is not an efficient solution. So there is a paragraph mode for sed which allows you to work with one paragraph at a time.

sed '
    /./ {          # If it is not a blank line
        H;         # Append the pattern space to hold space
        $!d        # Delete it if it is not the last line
    }
    x              # When we encounter a blank line, we swap the pattern and hold space
    s/\n//         # We remove the first empty newline
    s/\n/,/g       # Replace all newlines with ,
    $!G            # If it not the last line swap hold and pattern space for blank lines
' file

One-liner form:

sed '/./{H;$!d};x;s/\n//;s/\n/,/g;$!G' file

Output in both cases:

Aggr2_N1_SATA,Normal,192.168.1.2:/floluesxprd5_ds_vol1,Unknown,522.50 GB,478.69 GB,NFS,10/14/2020 3:21:52 PM,Enabled,Disabled,Not supported

boot_lun_svr1,Normal,NETAPP Fibre Channel Disk (naa.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx):3,Non-SSD,5.00 GB,4.29 GB,VMFS5,2/10/2020 4:26:37 PM,Enabled,Disabled,Supported

Upvotes: 2

jmunsch
jmunsch

Reputation: 24089

Based on this answer (Format output in columns [bash, grep, sed, awk]) if every eleven rows are being transposed:

printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n" $(sed 's/ /_/g' file_name) | sed 's/_/ /g'

Upvotes: 0

clt60
clt60

Reputation: 63902

Maybe this could works

perl -00 -F"\n" -lanE 'say join(",", @F)'

prints

Aggr2_N1_SATA,Normal,192.168.1.2:/floluesxprd5_ds_vol1,Unknown,522.50 GB,478.69 GB,NFS,10/14/2020 3:21:52 PM,Enabled,Disabled,Not supported
boot_lun_svr1,Normal,NETAPP Fibre Channel Disk (naa.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx):3,Non-SSD,5.00 GB,4.29 GB,VMFS5,2/10/2020 4:26:37 PM,Enabled,Disabled,Supported

and the

 perl -00 -F"\n" -lanE 'say join(",", @F),"\n"'

prints

Aggr2_N1_SATA,Normal,192.168.1.2:/floluesxprd5_ds_vol1,Unknown,522.50 GB,478.69 GB,NFS,10/14/2020 3:21:52 PM,Enabled,Disabled,Not supported

boot_lun_svr1,Normal,NETAPP Fibre Channel Disk (naa.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx):3,Non-SSD,5.00 GB,4.29 GB,VMFS5,2/10/2020 4:26:37 PM,Enabled,Disabled,Supported

Upvotes: 0

glenn jackman
glenn jackman

Reputation: 246774

perl:

perl -00 -lpe 's/\n/,/g' file

Upvotes: 9

choroba
choroba

Reputation: 241838

Perl solution:

perl -pe '$comma and !/^$/ and  print "," ;$comma = !/^$/ and chomp or print "\n"' input

Upvotes: 0

konsolebox
konsolebox

Reputation: 75478

awk -v RS= -v OFS=, '{$1 = $1} 1' file

Output:

Aggr2_N1_SATA,Normal,192.168.1.2:/floluesxprd5_ds_vol1,Unknown,522.50 GB,478.69 GB,NFS,10/14/2020 3:21:52 PM,Enabled,Disabled,Not supported    
boot_lun_svr1,Normal,NETAPP Fibre Channel Disk (naa.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx):3,Non-SSD,5.00 GB,4.29 GB,VMFS5,2/10/2020 4:26:37 PM,Enabled,Disabled,Supported

With spaces between:

awk -v RS= -v OFS=, '{$1 = $1} NR > 1 { print "" } 1' file

Output:

Aggr2_N1_SATA,Normal,192.168.1.2:/floluesxprd5_ds_vol1,Unknown,522.50 GB,478.69 GB,NFS,10/14/2020 3:21:52 PM,Enabled,Disabled,Not supported

boot_lun_svr1,Normal,NETAPP Fibre Channel Disk (naa.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx):3,Non-SSD,5.00 GB,4.29 GB,VMFS5,2/10/2020 4:26:37 PM,Enabled,Disabled,Supported

With spaces after every line:

awk -v RS= -v OFS=, -v ORS='\n\n' '{$1 = $1} 1' file

Upvotes: 6

Related Questions