GSG
GSG

Reputation: 71

Transposing multiple columns in multiple rows keeping one column fixed in Unix

I have one file that looks like below

1234|A|B|C|10|11|12  
2345|F|G|H|13|14|15  
3456|K|L|M|16|17|18  

I want the output as

1234|A  
1234|B  
1234|C  
2345|F  
2345|G  
2345|H  
3456|K  
3456|L  
3456|M

I have tried with the below script.

awk -F"|" '{print $1","$2","$3","$4"}' file.dat | awk -F"," '{OFS=RS;$1=$1}1'

But the output is generated as below.

1234  
A  
B  
C  
2345  
F  
G  
H  
3456  
K  
L  
M  

Any help is appreciated.

Upvotes: 1

Views: 114

Answers (3)

mrqiao001
mrqiao001

Reputation: 152

# perl -lne'($a,@b)=((split/\|/)[0..3]);foreach (@b){print join"|",$a,$_}' file.dat

1234|A
1234|B
1234|C
2345|F
2345|G
2345|H
3456|K
3456|L
3456|M

Upvotes: 0

The fourth bird
The fourth bird

Reputation: 163477

If you want to do this dynamically, then you could pass in the number of fields that you want, and then use a loop starting from the second field.

In the script, you might first check if the number of fields is equal or greater than the number you pass into the script (in this case n=4)

awk -F\| -v n=4 '
NF >= n {
  for(i=2; i<=n; i++) print $1 "|" $i
}
' file

Output

1234|A
1234|B
1234|C
2345|F
2345|G
2345|H
3456|K
3456|L
3456|M

Upvotes: 0

Jens
Jens

Reputation: 72717

What about a single simple awk process such as this:

$ awk -F\| '{print $1 "|" $2 "\n" $1 "|" $3 "\n" $1 "|" $4}' file.dat
1234|A
1234|B
1234|C
2345|F
2345|G
2345|H
3456|K
3456|L
3456|M

No messing with RS and OFS.

Upvotes: 1

Related Questions