2016-07-03 43 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 }}}應該發生什麼?如果你實際上需要平衡大括號,這就把它從常規語言領域轉化爲上下文無關語言,這將需要更強大的工具。

鑑於您的用戶名,您可能需要閱讀關於正式語言和自動機理論的書籍。它可能是「老」的技術,但它是非常強大的,並通過各種技術整天使用。

相關問題