4

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

4

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.

  • apreciate but I got sed: invalid option -- E – irom Sep 14 '17 at 18:22
  • @irom What OS are you on? Try -r in place on -E. – John1024 Sep 14 '17 at 18:26
  • Changing your solution to use BREs is pretty much trivial. – Satō Katsura Sep 14 '17 at 18:32
  • This is old rhel 5;) – irom Sep 14 '17 at 18:36
  • @irom Very good. Old GNU used -r instead of -E. Otherwise, escape the parens as I show in the updated answer and neither option is needed. – John1024 Sep 14 '17 at 18:37
5

with awk:

awk '{line1=$0; getline line2; getline line3; print line1, line3, line2}' file
1

With ex and printf:

printf '%s\n' 'g/^O/+m +2' 'g/^O/j 3' %p | ex file.txt

Change the %p to an x to actually save changes when you're happy with the output.


globally, on lines starting (^) with a capital O, move (m) the next line (+) to after the second-next line (+2).

Then, globally, on each line starting with O, join three lines together.

Print all lines %p.

Or, save and exit x.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.