2015-07-21 66 views
1

我正在使用C#編寫Visual Studio 2013 Express中的正則表達式。我試圖把周圍的包括文字和@#$%^ * &()_-不同的是每一個字符串單引號:C#中的正則表達式如何只替換捕獲組而不是非捕獲組

  • 沒有
  • 空( )
  • notempty()
  • 的currentdate()
  • 已經周圍有單引號的任何字符串。

這裏是我的正則表達式和它用來做什麼的樣本: https://regex101.com/r/nI1qP0/1

我希望把單引號僅圍繞捕捉組,離開非捕捉組不變。我知道這可以用lookarounds來完成,但我不知道如何。

回答

1

而不是試圖忽略帶有單詞和!@#$%^ & *()_-的字符串,我只是將它們包含在我的搜索中,在兩端放置了額外的單引號,然後全部刪除這樣的兩個單引號的實例:

// Find any string of words and [email protected]#$%^&*()_- in and out of quotes. 
Regex getwords = new Regex(@"(^(?!and\b)(?!or\b)(?!not\b)(?!empty\b)(?!notempty\b)(?!currentdate\b)([\[email protected]#$%^&*())_-]+)|((?!and\b)(?!or\b)(?!not\b)(?!empty\b)(?!notempty\b)(?!currentdate\b)(?<=\W)([\[email protected]#$%^&*()_-]+)|('[\w\[email protected]#$%^&*()_-]+')))", RegexOptions.IgnoreCase); 
// Find all cases of two single quotes 
Regex getQuotes = new Regex(@"('')"); 

// Get string from user 
Console.WriteLine("Type in a string"); 
string search = Console.ReadLine(); 

// Execute Expressions. 
search = getwords.Replace(search, "'$1'"); 
search = getQuotes.Replace(search, "'"); 
+1

很棒,你找到了適合你的解決方案。請考慮提供對您有幫助的答案。 –

+2

因爲我是堆棧溢出的新手,所以現在我的能力已經超過了15我可以。 – brandonstrong

1

你可以使用這個表達式:

(?:'[^']*'|(?:\b(?:(?:not)?empty|currentdate)\(\)|and|or|not))|([[email protected]#$%^&*_.\w-]‌​+) 

這裏忽略匹配不捕獲和被引用的話可以使用Match.Groups[1]進行檢索。然後,您可以在Match.Groups[1]左右添加引號,並根據需要更換整個輸入。

RegEx Demo

+0

這很接近,但它不會捕獲任何字符!@#$%^&*()-_。即使我將它們添加到(\ w +)部分中([!@#$%^&*()_- w /] +),如果它們位於單詞的最後,它也不起作用。 – brandonstrong

+0

'!@#$%^&*()'不被視爲單詞字符,而是每寫一個單詞**。你可以使用這個正則表達式:'(?:'[^'] *'|(?:\ b(?:(?: not)?empty | currentdate)\(\)| and | or | not))|( [!@#$%^&* _ \ W - ] +)'。看到這個演示:https://regex101.com/r/nI1qP0/3 – anubhava

+1

你是對的,我犯了一個錯誤。對於那個很抱歉。這個很好。 – brandonstrong

1

你需要使用一個匹配評估,或回調方法。重點是你可以檢查這個方法中的匹配和捕獲的組,並根據你的模式決定採取什麼動作。

因此,添加這個回調方法(可能非靜態如果調用方法是非靜態):

public static string repl(Match m) 
{ 
    return !string.IsNullOrEmpty(m.Groups[1].Value) ? 
     m.Value.Replace(m.Groups[1].Value, string.Format("'{0}'", m.Groups[1].Value)) : 
     m.Value; 
} 

然後,使用一個overload of Regex.Replace with the match evaluator (=callback method)

var s = "'This is not captured' but this is and not or empty() notempty() currentdate() capture"; 
var rx = new Regex(@"(?:'[^']*'|(?:\b(?:(?:not)?empty|currentdate)\(\)|and|or|not))|([[email protected]#$%^&*_.\w-]+)"); 
Console.WriteLine(rx.Replace(s, repl)); 

注意可以縮短用lambda表達式的代碼:

Console.WriteLine(rx.Replace(s, m => !string.IsNullOrEmpty(m.Groups[1].Value) ? 
    m.Value.Replace(m.Groups[1].Value, string.Format("'{0}'", m.Groups[1].Value)) : 
    m.Value)); 

參見IDEONE demo