简体   繁体   中英

Replace ${abc} in text file using Perl, but not \${abc}

The title sort of says it all. I have a text file (NOT a perl file), which contains any number of placeholders over many lines and possibly several on the same line. Here's an example:

Hello ${first} ${last}, please visit us at http://${host}${context} and mind the \${variables}.

I need to replace everything that looks like ${...} but not what looks like \${...} . So this example needs to convert to:

Hello John Doe, please visit us at http://example.com/foobar and mind the \${variables}.

My expression currently looks like this:

s/([^\\])\$\{\s*([^\}\s]+)\s*\}/$1. _lookupVar( $2, $varMap )/ge

where _lookupVar is a function that knows how to insert the right value. I have the first [^\\] there in order to avoid replacing \${...} sequences, but this means that for ${host}${context} , only ${host} gets replaced. And for various reasons, I can't really turn ${host}${context} into ${host} ${context} .

I can hack something, but I was wondering whether I'm missing some regex magic that somebody knowledgeable might like to teach me;-)

Use a negative lookbehind assertion (?<!\\) rather than a negative character class [^\\] :

s/(?<!\\)\$\{\s*([^\}\s]+)\s*\}/_lookupVar($1, $varMap)/ge

The character class consumes the character just behind the $ (resulting in you having to put it back with $1 ), while the negative lookbehind simply checks to see if there's a \ there; if not, match the pattern.

To allow cases like:

\\${foo}

You could use something like:

s/(?<!\\)(?:\\\\)* \K \${ \s* ([^\s}]+) \s* }/_lookupVar($1, $varMap)/gxe

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM