Valentin Luque
Valentin Luque

Reputation: 35

How to replace string depending on whether it is odd or even

I m trying to replace a string "::" on a plain text for <b> or </b>. Depending of the first or second match without result with sed. The goal here is that the second tag </b> can be at the end of a paragraph not at the end of a line. i.e:

::Habiéndose calmado de distracciones, uno permanece completamente, 
y la naturaleza superior es vista con los ojos de la sabiduría.::

must be

<b>Habiéndose calmado de distracciones, uno permanece completamente, 
y la naturaleza superior es vista con los ojos de la sabiduría.</b>

I try it without result:

sed "s|::\(.*\)|\\<b>\1\</b>|g" EntrenamientoProgresivoSamadhi

Upvotes: 0

Views: 180

Answers (4)

potong
potong

Reputation: 58463

This might work for you (GNU sed):

sed ':a;/::/{x;s/^/x/;/xx/{s///;x;s/::/<\/b>/;ba};x;s/::/<b>/;ba}' file

If a line contains ::, swap to the hold space and increment a counter by inserting an x at the start of the line.

If the counter is 2 i.e. the swap space contains xx, reset the counter and then swap back to the pattern space and replace :: by <\b> and go again (in the case that a line contains 2 or more :: strings).

Otherwise, swap back to the pattern space and replace :: by <b and go again (for reasons explained above).

All other lines are untouched.

Upvotes: 0

Barmar
Barmar

Reputation: 781503

Use awk and increment a counter variable. Then you can perform a different substitution depending on whether it's odd or event.

awk '/::/ && counter++ % 2 == 0 {sub("::", "<b>") }
     /::/ {sub("::", "</b>") }
     1' 

Note that this will only work correctly if the start and end :: are on different lines.

Upvotes: 1

sseLtaH
sseLtaH

Reputation: 11237

Using GNU sed

$ sed -Ez 's~::(.[^:]*)::~<b>\1</b>~' input_file
<b>Habiéndose calmado de distracciones, uno permanece completamente, 
y la naturaleza superior es vista con los ojos de la sabiduría.</b>

Upvotes: 1

markp-fuso
markp-fuso

Reputation: 34808

Assumptions:

  • :: can occur more than once on a given line of input
  • :: never shows up as data (ie, we need to replace all occurrences of ::)
  • a solution using awk is acceptable

Adding some more data to our input:

$ cat file
::Habiéndose calmado de distracciones, uno permanece completamente,
y la naturaleza superior es vista con los ojos de la sabiduría.::
some more ::text1:: and then some more ::text2:: the end

One awk idea:

awk '
BEGIN { tag[0]="<b>"; tag[1]="</b>" }
      { while (sub(/::/,tag[c%2])) c++; print }
' file

This generates:

<b>Habiéndose calmado de distracciones, uno permanece completamente,
y la naturaleza superior es vista con los ojos de la sabiduría.</b>
some more <b>text1</b> and then some more <b>text2</b> the end

Upvotes: 1

Related Questions