Transpose rows to certain columns

Hello,

I have the following data and I want to use awk to transpose each value to a certain column , so in case the value is not available the column should be empty.

Example:

Box Name: BoxA
Weight: 1
Length :2
Depth :3
Color: red
Box Name: BoxB
Weight: 3
Length :4
Color: Yellow
Box Name: BoxC
Weight: 5
Length :6
Depth :7
Box Name: BoxD
Weight: 8
Length :9

Desired Ouput:

Box Name,Weight,Length,Depth,Color
BoxA,1,2,3,red
BoxB,3,4,,Yellow
BoxC,5,6,7,
BoxD,8,9,,

Thanks you,

Where exactly are you stuck with your attempt(s)?
Have you considered searching these forums? This is a very common ask.
Have you considered looking at the bottom of this thread for a list of suggested "hints"?

Please show what you've attempted so far....

1 Like

Hi,

Actually I don't have much experience in using awk. I got as far as transposing the columns and stuck there.

I used this

cat boxes.txt
Box Name: BoxA
Weight: 1
Length :2
Depth :3
Color: red
Box Name: BoxB
Weight: 3
Length :4
Color: Yellow
Box Name: BoxC
Weight: 5
Length :6
Depth :7
Box Name: BoxD
Weight: 8
Length :9
cat boxes.txt | awk '/^Box/ && c{print c;c=""}{c=c $0" "}END{if(c) print c}'
Box Name: BoxA Weight: 1 Length :2 Depth :3 Color: red
Box Name: BoxB Weight: 3 Length :4 Color: Yellow
Box Name: BoxC Weight: 5 Length :6 Depth :7
Box Name: BoxD Weight: 8 Length :9

I read the related threads in this forum but didn't find what I am looking for since the data is not identical for each row.

Thanks,

Hi rahman.ahmed,
Welcome to the UNIX.com forums.

When starting a new thread it always helps if you tell us what operating system and shell you're using. Various utilities on different systems have options that vary form operating system to operating system and shells are notorious for offering different sets of features above and beyond those that are in almost all shells. If we know what operating system and shell you're using, we are less likely to make suggestions that won't work in your environment.

We are here to help you learn how to do things like this on your own; not to act as your unpaid programming staff. If you show us what you have tried to solve a problem on your own (posting your code in CODE tags) along with the sample input that you provided (please surround sample input data in CODE tags) and the output you hope to produce from that data (also, please in CODE tags) we can make better suggestions to help you get around whatever was keeping you from your goal.

In a case like this one might try something like:

awk -v Headers="Box Name,Weight,Length,Depth,Color" '
BEGIN {	# Split the Headers given to us into field names and print the output
	# header line.  Set NHdrs to the number of fields to be printed in each
	# output record.  Set elements of the subscript[] array to have the 
	# output field name as a subscript and the output field position as the
	# value.
	NHdrs = split(Headers, Hdrs, /,/)
	for(i = 1; i <= NHdrs; i++) {
		subscript[Hdrs] = i
		printf("%s%s", Hdrs, (i == NHdrs) ? ORS : ",")
	}
	# Since the input field separator is sometimes <colon><space> and
	# sometimes <space><colon>, we will use a <colon> surrounded by any
	# number of <space>s as our field separator:
	FS = " *: *"
}

# Define a function to print an output record if any input data has been seen
# since we last printed a record.
function print_record(	loop) {
	if(data) {
		data = 0
		for(loop = 1; loop <= NHdrs; loop++)
			printf("%s%s", field[loop], (loop == NHdrs) ? ORS : ",")
		split("", field)
	}
}

NF {	# We have an input field on this line, gather the data and skip to the
	# next input record.
	field[subscript[$1]] = $2
	data++
	next
}

{	# Since there is no input fields on this line, print the data
	# accumulated from the previous lines as an output record.
	print_record()
}

END {	# In case there was no empty line at the end of the input file, also
	# print the data accumulated from the previous lines when we hit EOF.
	print_record()
}' file
2 Likes

Adapted this proposal published umpteen times in these forums to the requestor's sample

awk -F":"       '
BEGIN           {print HD = "Box Name,Weight,Length,Depth,Color"
                 for (MX=n=split (HD, HDArr, ","); n; n--) SRCH[HDArr[n]]
                }
NR > 1 &&
$0 ~ HDArr[1]   {for (i=1; i<=MX; i++) printf "%s%s", RES[HDArr], (i == MX)?ORS:OFS
                 delete RES
                }

                {gsub (/ *: */, ":")
                }

$1 in SRCH      {RES[$1] = $2
                }

END             {for (i=1; i<=MX; i++) printf "%s%s", RES[HDArr], (i == MX)?ORS:OFS
                }

' OFS="," file
Box Name,Weight,Length,Depth,Color
BoxA,1,2,3,red
BoxB,3,4,,Yellow
BoxC,5,6,7,
BoxD,8,9,,
3 Likes

Don Cragun and RudiC ,

Thank you very much for your fast responses and help. I really appreciate it .

The proposed solution worked perfectly , The bash version I'm running is GNU bash, version 4.2.47(1)-release (x86_64-suse-linux-gnu)

Thanks again.

1 Like