2009-12-16 151 views
0

好的...我有一個問題不能令人滿意的解決方案。替換可變數量的項目...正則表達式?

問題是我有輸入像這樣:

{sup 19}F({sup 3}He,t){sup 19}Ne(p){sup 18}F 

和需要輸出像這樣:

¹⁹F(³He,t)¹⁹Ne(p)¹⁸F 

我使用一系列替換的第一分裂各{SUP XX}部分的轉換爲{sup x} {sup x},然後使用正則表達式來匹配每個字符,並用它們的UTF-8單個替換字符替換字符。 「問題」是{sup}部分可以有數字1,2或3位數字(也許更多,我不知道),我想將它們「展開」爲單獨的{sup}部分,每個部分各有一個數字。 (我也有{}子對標同樣的問題...)

我目前的解決方案看起來像這樣(在Java中):

retval = retval.replaceAll("\\{sup ([1-9])([0-9])\\}", "{sup $1}{sup $2}"); 
retval = retval.replaceAll("\\{sup ([1-9])([0-9])([0-9])\\}", "{sup $1}{sup $2}{sup $3}"); 

我的問題:有沒有辦法在這樣做無論有多少位數字(或者至少是一些合理的數字),都可以單次傳遞?

回答

3

是的,但它可能有點破解,你必須小心它不會overshch

正則表達式:

(?:\{sup\s)?(\d)(?=\d*})}? 

替換字符串:

{sup $1} 

的簡短解釋:

(?:       | start non-capturing group 1 
    \{       | match the character '{' 
    sup       | match the substring: "sup" 
    \s       | match any white space character 
)        | end non-capturing group 1 
?        | ...and repeat it once or not at all 
(        | start group 1 
    \d       | match any character in the range 0..9 
)        | end group 1 
(?=       | start positive look ahead 
    \d       | match any character in the range 0..9 
    *       | ...and repeat it zero or more times 
    }       | match the substring: "}" 
)        | stop negative look ahead 
}        | match the substring: "}" 
?        | ...and repeat it once or not at all 

用簡單的英語:這一個單一的數字匹配,尋找只有當未來有一箇中間有可選數字的}。如果可能的話,子字符串{sup}也被替換。

編輯:

一個更好的一個是這樣的:

(?:\{sup\s|\G)(\d)(?=\d*})}? 

這樣一來,像串"set={123}"在數字不會被取代。我的第二個正則表達式中的\G與上一場比賽結束的地方相匹配。

+0

爲什麼您將'{sup'部分標記爲可選項?它看起來會匹配「1}」。 –

+0

@Mike:OP希望用'{sup 1} {sup 2} {sup 3}'來代替'{sup 123}'。只有第一個數字前面有'{sup',最後一個數字後面有'}':這就是爲什麼它是可選的。 –

+0

@Mike:啊,我明白你的意思了。因此,我的評論「你必須小心,它不會*超過*!」。看到我的第二個解決方案,那個解決方案就是'\ G'。 –

0

當然,這是一個標準的正則表達式構造。您可以在Pattern Javadoc中找到所有元字符,但出於您的目的,您可能需要「+​​」元字符或{1,3}貪婪量詞。鏈接中的詳細信息。

+0

不,你誤解了,OP不在尋找如何匹配一個或多個數字。 –

1

執行此類事情的最簡單方法是使用PHP的preg_replace_callback或.NET的MatchEvaluator代表。 Java沒有像內置的那樣的東西,但它確實公開了允許你自己實現它的底層API。下面是做這件事:

import java.util.regex.*; 

public class Test 
{ 
    static String sepsup(String orig) 
    { 
    Pattern p = Pattern.compile("(\\{su[bp])(\\d+)\\}"); 
    Matcher m = p.matcher(orig); 
    StringBuffer sb = new StringBuffer(); 
    while (m.find()) 
    { 
     m.appendReplacement(sb, ""); 
     for (char ch : m.group(2).toCharArray()) 
     { 
     sb.append(m.group(1)).append(ch).append("}"); 
     } 
    } 
    m.appendTail(sb); 
    return sb.toString(); 
    } 

    public static void main (String[] args) 
    { 
    String s = "{sup 19}F({sup 3}He,t){sub 19}Ne(p){sup 18}F"; 
    System.out.println(s); 
    System.out.println(sepsup(s)); 
    } 
} 

結果:

{sup 19}F({sup 3}He,t){sub 19}Ne(p){sup 18}F 
{sup 1}{sup 9}F({sup 3}He,t){sub 1}{sub 9}Ne(p){sup 1}{sup 8}F 

如果你願意,你可以繼續並生成該標和下標字符,並將這些來代替。