标题类型说明了一切。我有一个文本文件(不是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}
。
我可以破解某些东西,但我想知道我是否缺少一些知识渊博的人可能会教我的正则魔法; - )
答案 0 :(得分:4)
使用否定的lookbehind断言(?<!\\)
而不是负面的字符类[^\\]
:
s/(?<!\\)\$\{\s*([^\}\s]+)\s*\}/_lookupVar($1, $varMap)/ge
角色类消耗$
后面的角色(导致你必须用$1
将其放回),而负面的后视只是检查是否有\
那里;如果没有,请匹配模式。
答案 1 :(得分:1)
允许以下情况:
\\${foo}
您可以使用以下内容:
s/(?<!\\)(?:\\\\)* \K \${ \s* ([^\s}]+) \s* }/_lookupVar($1, $varMap)/gxe