Skip to main content
added 5 characters in body
Source Link
Kusalananda
  • 355.8k
  • 42
  • 735
  • 1.1k

This is difficult to do as sed does not support look-arounds etc. (as you can do in a PCRE). It would be easier to reverse the string and replace the third occurrence of the reversed word from the start, then reverse again.

$ echo 'dog and foo and bar and baz land good' | rev | sed 's/\<dna\>/XXX/3' | rev
dog XXX foo and bar and baz land good
 

As for why your expression does not work, this looks like a bug. The back-reference \3 seem to be the string  baz land, as if the \b before and in .*\band\b never had any effect.

The command

sed -E 's/(.*)\<and\>((.*\<and\>){2})/\1XYZ\2/'

seems to do the right thing on OpenBSD with its native sed (which uses \< and \> instead of \b).

I have yet to find an existing bug report against GNU sed or GNU glibc about this, although I wouldn't be surprised if it was at least related to glibc bug 25322 (because, see below).

You can work around it by being a bit more verbose:

sed -E 's/(.*)\band\b(.*\band\b.*\band\b)/\1XYZ\2/'

This is difficult to do as sed does not support look-arounds etc. (as you can do in a PCRE). It would be easier to reverse the string and replace the third occurrence of the reversed word from the start, then reverse again.

$ echo 'dog and foo and bar and baz land good' | rev | sed 's/\<dna\>/XXX/3' | rev
dog XXX foo and bar and baz land good

As for why your expression does not work, this looks like a bug. The back-reference \3 seem to be the string  baz land, as if the \b before and in .*\band\b never had any effect.

The command

sed -E 's/(.*)\<and\>((.*\<and\>){2})/\1XYZ\2/'

seems to do the right thing on OpenBSD with its native sed.

I have yet to find an existing bug report against GNU sed or GNU glibc about this, although I wouldn't be surprised if it was at least related to glibc bug 25322 (because, see below).

You can work around it by being a bit more verbose:

sed -E 's/(.*)\band\b(.*\band\b.*\band\b)/\1XYZ\2/'

This is difficult to do as sed does not support look-arounds etc. (as you can do in a PCRE). It would be easier to reverse the string and replace the third occurrence of the reversed word from the start, then reverse again.

$ echo 'dog and foo and bar and baz land good' | rev | sed 's/\<dna\>/XXX/3' | rev
dog XXX foo and bar and baz land good
 

As for why your expression does not work, this looks like a bug. The back-reference \3 seem to be the string  baz land, as if the \b before and in .*\band\b never had any effect.

The command

sed -E 's/(.*)\<and\>((.*\<and\>){2})/\1XYZ\2/'

seems to do the right thing on OpenBSD with its native sed (which uses \< and \> instead of \b).

I have yet to find an existing bug report against GNU sed or GNU glibc about this, although I wouldn't be surprised if it was at least related to glibc bug 25322 (because, see below).

You can work around it by being a bit more verbose:

sed -E 's/(.*)\band\b(.*\band\b.*\band\b)/\1XYZ\2/'
added 140 characters in body
Source Link
Kusalananda
  • 355.8k
  • 42
  • 735
  • 1.1k

This is difficult to do as sed does not support look-arounds etc. (as you can do in a PCRE). It would be easier to reverse the string and replace the third occurrence of the reversed word from the start, then reverse again.

$ echo 'dog and foo and bar and baz land good' | rev | sed 's/\<dna\>/XXX/3' | rev
dog XXX foo and bar and baz land good

As for why your expression does not work, this looks like a bug. The back-reference \3 seem to be the string  baz land, as if the \b before and in .*\band\b never had any effect.

The command

sed -E 's/(.*)\<and\>((.*\<and\>){2})/\1XYZ\2/'

seems to do the right thing on OpenBSD with its native sed.

I have yet to find an existing bug report against GNU sed or GNU glibc about this, although I wouldn't be surprised if it was at least related to glibc bug 25322 (because, see below).

You can work around it by being a bit more verbose:

sed -E 's/(.*)\band\b(.*\band\b.*\band\b)/\1XYZ\2/'

This is difficult to do as sed does not support look-arounds etc. (as you can do in a PCRE). It would be easier to reverse the string and replace the third occurrence of the reversed word from the start, then reverse again.

$ echo 'dog and foo and bar and baz land good' | rev | sed 's/\<dna\>/XXX/3' | rev
dog XXX foo and bar and baz land good

As for why your expression does not work, this looks like a bug. The back-reference \3 seem to be the string  baz land, as if the \b before and in .*\band\b never had any effect.

The command

sed -E 's/(.*)\<and\>((.*\<and\>){2})/\1XYZ\2/'

seems to do the right thing on OpenBSD with its native sed.

I have yet to find an existing bug report against GNU sed or GNU glibc about this.

You can work around it by being a bit more verbose:

sed -E 's/(.*)\band\b(.*\band\b.*\band\b)/\1XYZ\2/'

This is difficult to do as sed does not support look-arounds etc. (as you can do in a PCRE). It would be easier to reverse the string and replace the third occurrence of the reversed word from the start, then reverse again.

$ echo 'dog and foo and bar and baz land good' | rev | sed 's/\<dna\>/XXX/3' | rev
dog XXX foo and bar and baz land good

As for why your expression does not work, this looks like a bug. The back-reference \3 seem to be the string  baz land, as if the \b before and in .*\band\b never had any effect.

The command

sed -E 's/(.*)\<and\>((.*\<and\>){2})/\1XYZ\2/'

seems to do the right thing on OpenBSD with its native sed.

I have yet to find an existing bug report against GNU sed or GNU glibc about this, although I wouldn't be surprised if it was at least related to glibc bug 25322 (because, see below).

You can work around it by being a bit more verbose:

sed -E 's/(.*)\band\b(.*\band\b.*\band\b)/\1XYZ\2/'
deleted 78 characters in body
Source Link
Kusalananda
  • 355.8k
  • 42
  • 735
  • 1.1k

This is difficult to do as sed does not support look-arounds etc. (as you can do in a PCRE). It would be easier to reverse the string and replace the third occurrence of the reversed word from the start, then reverse again.

$ echo 'dog and foo and bar and baz land good' | rev | sed 's/\<dna\>/XXX/3' | rev
dog XXX foo and bar and baz land good

As for why your expression does not work, this looks like a bug. If you investigate what theThe back reference-reference \3 contains (by inserting it inseem to be the replacement text), you will notice that it isstring   baz   land good even though, as if the expression that is supposedly matching that text is\b before and in .*\band\b never had any effect.

The command

sed -E 's/(.*)\<and\>((.*\<and\>){2})/\1XYZ\2/'

seems to do the right thing on OpenBSD with its native sed.

I have yet to find an existing bug report against GNU sed or GNU glibc about this.

You can work around it by being a bit more verbose:

sed -E 's/(.*)\band\b(.*\band\b.*\band\b)/\1XYZ\2/'

This is difficult to do as sed does not support look-arounds etc. (as you can do in a PCRE). It would be easier to reverse the string and replace the third occurrence of the reversed word from the start, then reverse again.

$ echo 'dog and foo and bar and baz land good' | rev | sed 's/\<dna\>/XXX/3' | rev
dog XXX foo and bar and baz land good

As for why your expression does not work, this looks like a bug. If you investigate what the back reference \3 contains (by inserting it in the replacement text), you will notice that it is baz land good even though the expression that is supposedly matching that text is .*\band\b.

The command

sed -E 's/(.*)\<and\>((.*\<and\>){2})/\1XYZ\2/'

seems to do the right thing on OpenBSD with its native sed.

I have yet to find an existing bug report about this.

This is difficult to do as sed does not support look-arounds etc. (as you can do in a PCRE). It would be easier to reverse the string and replace the third occurrence of the reversed word from the start, then reverse again.

$ echo 'dog and foo and bar and baz land good' | rev | sed 's/\<dna\>/XXX/3' | rev
dog XXX foo and bar and baz land good

As for why your expression does not work, this looks like a bug. The back-reference \3 seem to be the string   baz  land, as if the \b before and in .*\band\b never had any effect.

The command

sed -E 's/(.*)\<and\>((.*\<and\>){2})/\1XYZ\2/'

seems to do the right thing on OpenBSD with its native sed.

I have yet to find an existing bug report against GNU sed or GNU glibc about this.

You can work around it by being a bit more verbose:

sed -E 's/(.*)\band\b(.*\band\b.*\band\b)/\1XYZ\2/'
added 483 characters in body
Source Link
Kusalananda
  • 355.8k
  • 42
  • 735
  • 1.1k
Loading
Source Link
Kusalananda
  • 355.8k
  • 42
  • 735
  • 1.1k
Loading