1

So I have the following regex that works, but not with sed

regex101

^(\S*HTTPS*_SERVER\S*)(\s*'https*:\/\/)(\S*)('\);)$

and the text in my file.txt:

define('HTTP_SERVER', 'http://localhost:31270');
define('HTTPS_SERVER', 'https://localhost:31270');

then when I try to do:

sed -i.bak -r 's/^\(\S*HTTPS*_SERVER\S*\)\(\s*\'https*:\/\/\)\(\S*\)\(\'\);\)$/\1\2test.com\4/' file.txt

it doesn't do anything.

Any ideas what it is wrong here? Is it because of the escaping char?

Edwin
  • 2,146
  • 20
  • 26
  • If you are using POSIX ERE, `\(` must be turned into `(` (and `\)` into `)`). Well, you might as well remove `-r` option. – Wiktor Stribiżew Aug 14 '17 at 11:30
  • I tried with -r and without, the same with escaping `(` and `)` or not escaping and still doesn't work – Edwin Aug 14 '17 at 11:32
  • 1
    Yes, I see, there is a `'` inside the pattern. You should use double quotes around `s/.../.../` command. – Wiktor Stribiżew Aug 14 '17 at 11:33
  • 1
    What version of sed are you using? The GNU version may support `\S` and `\s`, but I suspect no other varieties will. If you want to use posix classes, best to spell them out for clarity and portability. – ghoti Aug 14 '17 at 12:05
  • yes I use a GNU version (4.4), thanks for advice. – Edwin Aug 14 '17 at 12:28

2 Answers2

1

Since you are using POSIX ERE syntax (-r option) a capturing group is defined with a pair of unescaped ( and ). Besides, since you have a ' inside the pattern, you need to use doulbe quotes around the s/.../.../ command.

Use

sed -i.bak -r "s/^(\S*HTTPS*_SERVER\S*)(\s*'https*:\/\/)(\S*)('\);)$/\1\2test.com\4/" file.txt

See an online demo.

Note that you may use delimiters other than / to avoid escaping / symbols, in the pattern (say, you may use "s,<pattern>,<replacement>,", as there are no commas in the pattern itself). Besdies, as per this thread, if you really need to use a single quoted regex definition, you may replace a literal ' in the pattern with a \x27 entity.

Also, if you need not insert any text in between Group 1 and Group 2, you may merge the two group patterns into one, and - as you are removing Group 3, you do not even need to capture it.

So, an alternative could look like

sed -r 's,^(\S*HTTPS*_SERVER\S*\s*\x27https*://)\S*(\x27\);)$,\1test.com\2,' file.txt

See another online demo.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 1
    that is true, I found another work around https://stackoverflow.com/questions/24509214/how-to-escape-single-quote-in-sed which it uses `\x27` for the single quotes. But your explanation is a valid answer – Edwin Aug 14 '17 at 11:39
  • @Edwin Yes, the single quotes can be freely used if you define the regex within double quotes. – Wiktor Stribiżew Aug 14 '17 at 11:41
  • just to be an complete answer, maybe edit and add either the link to the single quote alternative or just add the solution to your answer. – Edwin Aug 14 '17 at 11:51
  • 1
    ah, you mean with `\x27` – Wiktor Stribiżew Aug 14 '17 at 11:53
1

You can reduce the number of capturing groups:

sed -E -i.bak "s/^(define\('HTTPS?_SERVER', 'https?:\/\/)[^']*('\);)/\1test.com\2/" file.txt
SLePort
  • 15,211
  • 3
  • 34
  • 44
  • 1
    that's an improvement to my regex, but not the answer to the question, tho I will up vote this! Thanks! – Edwin Aug 14 '17 at 11:42
  • Thanks @Edwin Wiktor Stribiżew's answer explains why your regex doesn't work with sed. My answer is just an alternative. – SLePort Aug 14 '17 at 11:50