2016-07-03 41 views
1

在POSIX shell脚本中,我需要查找所有出现在{{}}内的文本,并用星号替换文本和周围的大括号。如何在开始分隔符和结束分隔符之间进行匹配,使得文本不包含结束分隔符(即非贪婪匹配)?

例如,如果输入的是

{{ abc }} def {{ ghi {jkl} mno }} pqr 

那么输出必须

* def * pqr 

我一直没能拿出这个是工作的sed命令。

我尝试了几个命令,但他们不工作。例如,以下命令不会产生所需的输出,因为sed会进行贪婪匹配。它最终匹配{{ abc }} def {{ ghi {jkl} mno }}作为第一场比赛,而不仅仅是{{ abc }}

$ echo "{{ abc }} def {{ ghi {jkl} mno }} pqr" | sed 's/{{.*}}/*/g' 
* pqr 

下面是另一个不起作用的例子,因为它最终只匹配得太少。它与{{ ghi {jkl} mno }}(我们想要匹配)不匹配,因为这部分字符串包含}

$ echo "{{ abc }} def {{ ghi {jkl} mno }} pqr" | sed 's/{{[^}]*}}/*/g' 
* def {{ ghi {jkl} mno }} pqr 

我该怎么做这样的比赛?

我已经通过了Non greedy regex matching in sed?但方案有没有帮助,因为在这里我想匹配{{}}之间的一切,除了两个连续字符序列特异性,即}}。如果我试图在分隔符之间匹配除了单个字符之外的所有内容,那么对这个问题的答案会有所帮助。

回答

0

如果你有一个正则表达式匹配不包含"}}"的东西,那么你可以使用它作为"{{" exp "}}"。不幸的是,sed没有补码正则表达式运算符。许多正则表达式实现都是这样做的,因为常规语言的补充是常规的。所以我们知道它存在,但我们只需要手动构建它。

以比sed更易读的格式,接近的东西是"{{" ([^}]* ("}" [^}])?)* "}}"

在适当sed那就是:

$ echo "{{ abc }} def {{ ghi {jkl} mno }} pqr" \ 
    | sed 's/{{\([^}]*\(}[^}]\)\?\)*}}/*/g' 
* def * pqr 
$ 

这可能不是正是你这取决于你是否期待三个连胜括号想要什么。这个abc {{ def { ghi }}}应该发生什么?如果你实际上需要平衡大括号,这就把它从常规语言领域转化为上下文无关语言,这将需要更强大的工具。

鉴于您的用户名,您可能需要阅读关于正式语言和自动机理论的书籍。它可能是“老”的技术,但它是非常强大的,并通过各种技术整天使用。

相关问题