Eduard Florinescu
Eduard Florinescu

Reputation: 17511

Match one substring and replace another on same line

I want to change all true values to false for all lines that contain should-log substring, the input files contain other lines to but are not mentioned in this snippet:

logging.ap.should-log-headers = true
logging.ap.should-log-password = true
logging.api.should-log-headers = true
logging.httpbin.should-log-headers = true
logging.httpbin.should-log-password = true
logging.copy.should-log-headers = false
logging.copy.should-log-password = false
logging.test.should-log-headers = false
logging.test.should-log-password = false
logging.-test.should-log-password = true
logging.hu.should-log-headers = true
logging.madf.should-log-headers = true
logging.madf.should-log-password = true
logging.api-f-002.should-log-headers = true
logging.f.should-log-headers = true
logging.f-d.should-log-headers = true
logging.f-d.should-log-password = true
logging.copy-d.should-log-headers = false
logging.copy-d.should-log-password = false
logging.d.should-log-headers = false
logging.d.should-log-password = false
logging.e.should-log-headers = true
logging.e.should-log-password = true

what I am trying:

sed -i -E '/should-log=/{s/true/false/;}' infile

but it doesn't work, what am I doing wrong, how should I do it?

Upvotes: 2

Views: 75

Answers (2)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626689

Regex engine searches for matches from left to right. When you write should-log=, the search starts at the start of string and s is searched for. Once s is found, the regex engine checks the next char and if it is h, it goes on checking and once it gets to = after finding g, there is a failure, no = after g.

You need to make sure you allow the regex engine to actually get to (=consume) the part of the string you want.

Since after g you need to get to the first =, it is logical to match any zero or more chars other than =, so you can use

sed -i -E 's/(should-log[^=]*= *).*/\1false/' file

See the online demo. The POSIX ERE (see -E) regex matches

  • ( - start of a capturing group with ID 1 (its value is referred to with \1 from the replacement pattern):
    • should-log - a should-log sting
    • [^=]* - a negated bracket expression matching zero or more chars other than =
    • = - a = char
    • *
  • ) - end of the capturing group
  • .* - the rest of the line.

Note that sed -i -E '/should-log[^=]*=/s/true/false/' file is less precise as it might replace true that is not after should-log[^=]*=.

Upvotes: 1

Sundeep
Sundeep

Reputation: 23667

should-log= doesn't match any of the given input lines. You could use something like should-log- or should-log.*= or should-log-.*=.

Also, the {} grouping isn't needed for single command after the address.

Upvotes: 2

Related Questions