user1718482
user1718482

Reputation:

Perl literal regex

I need to search and substitute a regex. In fact the line:

^/httpd/$ (some chars here)

must be replaced with

^/httpd$ (value of a variable named VAR)

Therefore I used this:

perl -pi -e "s[^\Q^/httpd$\E(.*)$][\Q^/httpd$\E ${VAR}]" /file.conf

But nothing happens..

Upvotes: 0

Views: 307

Answers (2)

TLP
TLP

Reputation: 67900

You seem to have some confusion as to whether you have or want to have a trailing slash in your string, e.g. httpd/$ or httpd$. If you do have it and did not put it in the regex, that is why it does not match.

But besides that, it is not a good idea to try and interpolate shell variables in a regex in Perl code. You use the %ENV hash for that, where the $VAR environment variable is denoted $ENV{VAR}.

As for the \Q ... \E and the $, it seems to be quite the dilemma. Because variables can be interpolated, you cannot use $\E because it will be interpreted as $\ and the literal letter E. And you cannot escape the dollar sign because the \Q ... \E will escape the backslash. You can however, put the dollar sign outside the escape and escape it manually, e.g. \E\$.

You can also use the \K escape to "keep" parts of your string you do not want to remove.

Because you have not provided enough information, it is impossible to provide an exact answer, but I can guess. Here is my guess as to what you might need:

perl -pi -e 's[^\Q^/httpd/\E\$\K.*][ $ENV{VAR}]' /file.conf

Or perhaps more simply

perl -pi -e 's[^\^/httpd/\$\K.*][ $ENV{VAR}]' /file.conf

Upvotes: 2

Stephan
Stephan

Reputation: 43023

Try this syntax instead:

 perl -pi -e "s/\^\/httpd\/\\$.*/^\/httpd\\$ ${VAR}/" /file.conf

In the initial regex, a / is missing. The shell interprets the $ sign so perl doesn't "see" it in the regex.

Demo

file.conf

^/httpd/$ qsdfqsdfqsdfqsdf
^/httpd/$ qsdfqsdfqsdfqsdsdfgsdfgf
^/httpd/$ qsdfqsdfqsdfqszezezedf

main.sh

#!/bin/bash

VAR=FOOBAR

echo BEFORE
more file.conf

perl -pi -e "s/\^\/httpd\/\\$.{0,}/^\/httpd\\$ ${VAR}/" file.conf

echo
echo
echo AFTER
more file.conf

echo
echo
echo 'done'

OUTPUT

$bash -f main.sh 
BEFORE
::::::::::::::
file.conf
::::::::::::::
^/httpd/$ qsdfqsdfqsdfqsdf
^/httpd/$ qsdfqsdfqsdfqsdsdfgsdfgf
^/httpd/$ qsdfqsdfqsdfqszezezedf

AFTER
::::::::::::::
file.conf
::::::::::::::
^/httpd$ FOOBAR
^/httpd$ FOOBAR
^/httpd$ FOOBAR

done

Upvotes: -1

Related Questions