使用Perl替换文本文件中的$ {abc},但不是\ $ {abc}

时间:2011-07-14 23:11:01

标签: regex perl

标题类型说明了一切。我有一个文本文件(不是perl文件),它包含许多行中的任意数量的占位符,并且可能在同一行上有多个占位符。这是一个例子:

  

Hello $ {first} $ {last},请访问http:// $ {host} $ {context}   并注意\ $ {variables}。

我需要替换看起来像${...}但看起来不像\${...}的所有内容。所以这个例子需要转换为:

  

您好John Doe,请访问我们的http://example.com/foobar   并注意\ $ {variables}。

我的表达目前看起来像这样:

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

其中_lookupVar是一个知道如何插入正确值的函数。我有第一个[^\\],以避免替换\${...}序列,但这意味着对于${host}${context},只有${host}被替换。由于种种原因,我无法将${host}${context}转变为${host} ${context}

我可以破解某些东西,但我想知道我是否缺少一些知识渊博的人可能会教我的正则魔法; - )

2 个答案:

答案 0 :(得分:4)

使用否定的lookbehind断言(?<!\\)而不是负面的字符类[^\\]

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

角色类消耗$后面的角色(导致你必须用$1将其放回),而负面的后视只是检查是否有\那里;如果没有,请匹配模式。

答案 1 :(得分:1)

允许以下情况:

\\${foo}

您可以使用以下内容:

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