samuG
samuG

Reputation: 33

how to replace a string not followed by dot and at the end of the line

I have a line

echo "object smtp aaa smtp.asd.com server.smtp.com eq smtp"
object smtp aaa smtp.asd.com server.smtp.com eq smtp

and I need to replace the smtp with 25 but just were the smtp is standing alone. The expected output should be

object 25 aaa smtp.asd.com server.smtp.com eq 25

It is not possible to use the \b or < > boundaries because there is a comma. I've tried to use

echo "object smtp aaa smtp.asd.com server.smtp.com eq 25" | sed -E 's/smtp[^.]?$/25/g'
object smtp aaa smtp.asd.com server.smtp.com eq 25

but it replaces just match at the end of the line. The

echo "object smtp aaa smtp.asd.com server.smtp.com eq smtp" | sed -E 's/smtp[^.]?( |$)/25/g'
object 25aaa smtp.asd.com server.smtp.com eq 25

replaces also the space. Does somebody has an idea how to solve the problem?

Upvotes: 0

Views: 64

Answers (2)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627292

With a GNU sed, if you need to match smpt as a whole word that has no dot at the end, you can use

s="object smtp aaa smtp.asd.com server.smtp.com eq smtp"
sed -E 's/\bsmtp([^.]|$)/25\1/g' <<< "$s"

See the online demo. Details:

  • \b - a word boundary
  • smtp - smtp substring
  • ([^.]|$) - Capturing group 1 (\1 refers to this value in the replacement): any char other than a . char ([^.]), or (|) the end of string ($).

The same can be done with perl:

s="object smtp aaa smtp.asd.com server.smtp.com eq smtp"
perl -pe 's/\bsmtp\b(?!\.)/25/g' <<< "$s"

See this online demo.

Here, \bsmtp\b(?!\.) matches a whole word smtp (with \bsmtp\b) that is not immediately followed with a . char ((?!\.)).

Another solution with perl is to match smtp within whitespace boundaries:

perl -pe 's/(?<!\S)smtp(?!\S)/25/g' <<< "$s"

See this demo. However, in this case, it won't replace smtp in smtp-server since smtp in this case should be inside whitespaces or start/end of string.

Upvotes: 0

anubhava
anubhava

Reputation: 785761

You may use this sed:

s="object smtp aaa smtp.asd.com server.smtp.com eq smtp"
sed -E -e ':a' -e 's/(^|[[:blank:]])smtp([[:blank:]]|$)/\125\2/g;ta' <<< "$s"

object 25 aaa smtp.asd.com server.smtp.com eq 25

Here:

  • :a: Sets label a
  • s/(^|[[:blank:]])smtp([[:blank:]]|$)/\125\2/g replaces each smtp with 25 if it preceded by start position or whitespace and if it is followed by whitespace or end position
  • ta: Goes back to label a if substitution is successful

Online Demo

Upvotes: 1

Related Questions