Sed - How to match a regex group and use it to replace all other matched occurrences in the same line?

Viewed 139

I'm trying to repeat a matched pattern n times in the same line, depending on another match (Constant).

Input

Parent:X 4541, SomeData, Constant:Child: Variable1, SomeData, Constant:Child: Variable2, SomeData, Constant:Child: Variable3, SomeData, 
Parent:Y 2131, SomeData, Constant:Child: Variable4, SomeData, Constant:Child: Variable5, SomeData, Constant:Child: Variable6, SomeData, 
Parent:Z 51 F, SomeData, Constant:Child: Variable7, SomeData, Constant:Child: Variable8, SomeData, Constant:Child: Variable9, SomeData, 

Expected output

Parent:X 4541, SomeData, X 4541: Child: Variable1, SomeData, X 4541: Child: Variable2, SomeData, X 4541: Child: Variable3, SomeData, 
Parent:Y 2131, SomeData, Y 2131: Child: Variable4, SomeData, Y 2131: Child: Variable5, SomeData, Y 2131: Child: Variable6, SomeData, 
Parent:Z 51 F, SomeData, Z 51 F: Child: Variable7, SomeData, Z 51 F: Child: Variable8, SomeData, Z 51 F: Child: Variable9, SomeData, 

Note that I replaced every Constant with Parent's name.

I think sed hold space might be the answer, but I honestly couldn't do it.

If it helps solving the problem, I can break the lines before every Constant first:

Parent:X 4541, SomeData, 
Constant:Child: Variable1, SomeData, 
Constant:Child: Variable2, SomeData, 
Constant:Child: Variable3, SomeData, 
Parent:Y 2131, SomeData, 
Constant:Child: Variable4, SomeData, 
Constant:Child: Variable5, SomeData, 
Constant:Child: Variable6, SomeData, 
Parent:Z 51 F, SomeData, 
Constant:Child: Variable7, SomeData, 
Constant:Child: Variable8, SomeData, 
Constant:Child: Variable9, SomeData, 

and it doesn't matter if the output isn't in the same line:

Parent:X 4541, SomeData, 
 X 4541: Child: Variable1, SomeData, 
 X 4541: Child: Variable2, SomeData, 
 X 4541: Child: Variable3, SomeData, 
Parent:Y 2131, SomeData, 
 Y 2131: Child: Variable4, SomeData, 
 Y 2131: Child: Variable5, SomeData, 
 Y 2131: Child: Variable6, SomeData, 
Parent:Z 51 F, SomeData, 
 Z 51 F: Child: Variable7, SomeData, 
 Z 51 F: Child: Variable8, SomeData, 
 Z 51 F: Child: Variable9, SomeData, 

Efforts:

This will correctly replace the last Constant with the a line break followed by parent's name, but I've to repeat the command multiple times untill there is no match left (Not practical).

Sed -r -i "s#Parent:([^,]*)(.*)Constant:#\1\2\n\1: #" file

Using awk is fine, but it would be much appreciated if anyone can help with a sed command with some explanation.

3 Answers

A sed based on the code from your comment:

sed -E ':a;s/(Parent:([^,]*).*)Constant:/\1\2: /;t a' file

t is for "test". If a previous s/// was successful, it goes to the specified label, or to the end of the script.

Another awk solution:

awk -F '[,:]+' '{gsub(/ Constant:/, " " $2 ": ")} 1' file

Parent:X 4541, SomeData, X 4541: Child: Variable1, SomeData, X 4541: Child: Variable2, SomeData, X 4541: Child: Variable3, SomeData,
Parent:Y 2131, SomeData, Y 2131: Child: Variable4, SomeData, Y 2131: Child: Variable5, SomeData, Y 2131: Child: Variable6, SomeData,
Parent:Z 51 F, SomeData, Z 51 F: Child: Variable7, SomeData, Z 51 F: Child: Variable8, SomeData, Z 51 F: Child: Variable9, SomeData,

With your shown samples, please try following awk code.

awk 'BEGIN{FS=OFS=", "} {split($1,arr,":");gsub(/Constant:/,arr[2]": ")} 1' Input_file

To perform inplace saving run following code.

awk 'BEGIN{FS=OFS=", "} {split($1,arr,":");gsub(/Constant:/,arr[2]": ")} 1' Input_file > temp && mv temp Input_file
Related