Merging 3 consecutive lines with swap

awksed

Hey I need to merge three consecutive lines with swap between 2nd and 3rd line in 'file':

$cat file
Object Name: A
    comments: comment A
    manual_encdomain: Name: A 
Object Name: B
    comments: comment B
    manual_encdomain: Name: B 

So instead of output below :

$sed 'N;N;s/\n/ /g' file 
Object Name: A comments: comment A manual_encdomain: Name: A 
Object Name: B comments: comment B manual_encdomain: Name: B

I would rather need this

Object Name: A manual_encdomain: Name: A comments: comment A
Object Name: B manual_encdomain: Name: B comments: comment B

sed, awk anything

Best Answer

Yes, you can use sed to swap lines:

$ sed -E 'N;N;s/\n([^\n]*)\n([^\n]*)/ \2 \1/' file
Object Name: A     manual_encdomain: Name: A      comments: comment A
Object Name: B     manual_encdomain: Name: B      comments: comment B

Or, equivalently:

$ sed  'N;N;s/\n\([^\n]*\)\n\([^\n]*\)/ \2 \1/g' file
Object Name: A     manual_encdomain: Name: A      comments: comment A
Object Name: B     manual_encdomain: Name: B      comments: comment B

How it works:

  • -E

    This turns on extended regular expressions. (-E works on both BSD (OSX) sed and modern GNU sed. For older versions of GNU sed, use -r instead.)

    Without extended regex, we need to escape ( and ) as shown above.

  • N;N

    This reads in the second and third lines.

  • s/\n([^\n]*)\n([^\n]*)/ \2 \1/

    This swap the second and third lines. The first occurrence of \n([^\n]*) captures the second line and saves it in capture group 1. The second occurrence of \n([^\n]*) captures the third line and saves it in capture group 2. The replacement text, \2 \1 swaps the position while replacing the newlines with spaces.

Removing some excess white space

The second and third lines are indented in the input file. If we want to remove that extra whitespace:

$ sed -E 'N;N;s/\n[[:blank:]]*([^\n]*)\n[[:blank:]]*([^\n]*)/ \2 \1/g' file
Object Name: A manual_encdomain: Name: A  comments: comment A
Object Name: B manual_encdomain: Name: B  comments: comment B

[[:blank:]] is the unicode-safe way to match blanks and tabs.

Related Question