2016-03-04 88 views
1

我有用戶輸入的字符串,並希望標記它們。爲此,我想使用正則表達式,現在有一個特殊情況的問題。 的示例串是正則表達式標記問題

Test + "Hello" + "Good\"more" + "Escape\"This\"Test" 或C#相當於

@"Test + ""Hello"" + ""Good\""more"" + ""Escape\""This\""Test"""

我能夠匹配Test+令牌,但不包含那些的。「我用的是」讓用戶指定這是字面上的字符串而不是特殊的標記。現在,如果用戶想使用「字符串中的字符,我認爲這讓他以\逃避它的

所以規則是:給我的一切兩者之間」」,但在前面的字符最後的「不能是一個\」。

我期望的結果是:"Hello""Good\"more""Escape\"This\"Test" 我需要的「」字是在最後一場比賽,所以我知道這是一個字符串。

我現在有這給了我,結果如下正則表達式@"""([\w]*)(?<!\\"")""""Hello""more"​​

所以後面看看是不是工作,我希望它是。有誰知道正確的方式來獲得像我想要的字符串?

+1

還有一個級別:\通常可以用另一個\\ \ ...來轉義...所以'\\'''''''' – xanatos

+0

Xanatos是對的,否則,['「[^」\\] * (?:\\ [^ 「\\] *)*」'](http://regexstorm.net/tester?p=%22%5b%5e%22%5c%5c%5d*(%3F%圖3a%5C%5c所示。%圖5b%5E%22%5C%5C%5D *)*%22&I =測試+%2B +%22Hello%22 +%2B +%22Good%5C%22more%22 +%2B +%22%圖5c% 5c%5c%22Escape%5c%22This%5c%22Test%22&o = ixncsm)應該爲你工作(C#['var rx =「\」[^ \「\\\\] *(?:\\\\。 [^ \ 「\\\\] *)* \」「'](http://ideone.com/dTq91U))。 –

回答

1

這裏的一個正則表達式的適應我使用解析命令行:

(?!\+)((?:"(?:\\"|[^"])*"?|\S)+) 

here at regex101

(適配是負先行忽略+和檢查\"代替""

希望這可以幫助你。

問候。

編輯:

如果你不感興趣的包圍引號:

(?!\+)(?:"((?:\\"|[^"])*)"?|(\S+)) 
+0

這甚至會匹配['Test + \「Hello」+ \「Good \」more「+ \」Escape \「This \」Test「'](https://regex101.com/r/yE2vW7/2)。 –

1

爲了使它更安全,我建議讓轉義雙"..."具有以下的正則表達式中的所有字符串:

^(?:[^"\\]*(?:\\.[^"\\]*)*("[^"\\]*(?:\\.[^"\\]*)*"))+ 

它匹配

  • ^ - 非捕獲組1用作用於隨後的子模式
    • [^"\\]*(?:\\.[^"\\]*)*容器 - - 比賽0+字符以外的字符串(這樣我們就可以檢查每個"和逸出序列)
    • (?:的開始比"\隨後用\\. 0+序列(任何轉義序列),然後以比"\(因此,我們避免匹配被轉義第一",並且它可以與任何數量的電子商務前面其他0+字符花莖序列)
    • ("[^"\\]*(?:\\.[^"\\]*)*") - 捕獲組1匹配"..."子可能含有內部
  • )+任何轉義序列 - 被重複第一非捕獲組的端部1次或更多次

regex demo,這裏是一個C# demo

var rx = "^(?:[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"))+"; 
var s = @"Test + ""Hello"" + ""Good\""more"" + \""Escape\""This\""Test\"" + ""f"""; 
var matches = Regex.Matches(s, rx) 
     .Cast<Match>() 
     .SelectMany(m => m.Groups[1].Captures.Cast<Capture>().Select(p => p.Value).ToArray()) 
     .ToList(); 
Console.WriteLine(string.Join("\n", matches)); 

UPDATE

如果您需要刪除的標記,只是匹配,並且捕捉他們的一切外,此代碼:

var keep = "[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*"; 
var rx = string.Format("^(?:(?<keep>{0})\"{0}\")+(?<keep>{0})$", keep); 
var s = @"Test + ""Hello"" + ""Good\""more"" + \""Escape\""This\""Test\"" + ""f"""; 
var matches = Regex.Matches(s, rx) 
     .Cast<Match>() 
     .SelectMany(m => m.Groups["keep"].Captures.Cast<Capture>().Select(p => p.Value).ToArray()) 
     .ToList(); 
Console.WriteLine(string.Join("", matches)); 

another demo

輸出:Test + + + \"Escape\"This\"Test\" +@"Test + ""Hello"" + ""Good\""more"" + \""Escape\""This\""Test\"" + ""f""";

+0

這看起來非常好,但是對於標記我想用空字符串替換我的輸入字符串中的匹配,因爲我有多個表達式用於不同的目的,你的正則表達式使我匹配整個字符串,那麼最安全的是什麼我可以替換正則表達式中每個字符串的第一次出現,但我想知道這是否安全。 – RBS

+0

好的,所以你需要刪除''你好'',''好\「more」'和''f「',對嗎?讓我檢查一下... –

+0

檢查[此演示](http://ideone.com/MAIWJv)。 –