2017-02-17 100 views
1

我正在構建一個解析器,並且我想從各行刪除註釋。例如,使用正則表達式去除註釋

variable = "some//thing" ////actual comment 

評論標記是//。在這種情況下,variable將包含"some//thing",其他所有內容都將被忽略。我打算用正則表達式替換它。目前我正在使用(".*"|[ \t])*(\/\/.*)作爲正則表達式。但是替換完全替換"some//thing" ////actual comment

我找不到我應該使用的正則表達式。謝謝你的幫助。

其他信息 - 我使用C#與netcoreapp 1.1.0

編輯 - 某些情況下可能是一個線與就像//line comment評論。字符串也可能包含轉義引號。

+1

你解析一個現有的語言,或者這是一種自定義格式? – Ryan

+0

這是一種自定義語言 – Crimson7

+1

[本頁可能有所幫助](http://www.rexegg.com/regex-best-trick.html#notarzan)? '「[^」] *「|(//.*)',但不包括轉義的引號 - 例如''some \」// thing「'。 –

回答

1

這是醜陋的正則表達式模式。我相信它會運作良好。我已經嘗試了每個我能想到的病理學示例,包括包含語法錯誤的行。例如,引用的字符串含有太多的引號或太少,或者具有雙重轉義引號,因此,而不是轉義。並且在評論中引用了字符串,在我想提醒自己可以選擇時,我已經知道這些字符串。

,它絆倒了唯一的一次是,如果有一個看似引號字符串中雙斜槓,不知何故該字符串格式錯誤,雙斜槓合法結束的正確引用部分的外側。在語法上,它使得它成爲一個有效的評論,儘管不是程序員的意圖。所以,從程序員的角度來看,這是錯誤的,但根據規則,這真的是一個評論。意思是,這種模式似乎只是絆倒了。

使用時,模式將返回行的非註釋部分。該模式中有一個換行\n以允許將其應用於整個文件。如果您的系統以某種其他方式解釋換行符,例如\r\r\n,則可能需要修改。要在單行模式下使用它,如果您選擇,可以將其刪除。多行版本中的字符是17和18中的一行,並且是第五行,第六和第七個打印字符。但是,您可以放心地將其留在那裏,但是,與單行模式不同的是,它在多行模式下會返回一行換行符,換行符爲空白,或者在第一列開始註釋。如果將結果寫入新文件,這將保持原始版本和規定版本中的行號相同。使比較容易。

一個主要警告此模式:它使用一個分組構造,在正則表達式引擎中具有不同程度的支持。我相信在這裏使用,看看,只有.NET和PCRE引擎纔會接受YMMV。這是一種高等教育類型:(?(_condition_)_then_|_else_)_condition_模式被視爲零寬度斷言。如果模式匹配,則在嘗試匹配中使用_then_模式,否則使用_else_模式。如果沒有這種構造,這個模式就會變得不尋常,並且在我的一些病理測試案例中仍然沒有成功。

這裏介紹的模式是因爲它需要由正則表達式引擎來看。我是而不是是C#程序員,所以我不知道轉義引用字符串的所有細微差別。將這個模式放入你的代碼中,這樣所有的反斜槓和引號都可以被正則表達式引擎正確地看到。也許C#與Perl的heredoc語法相同。

這是使用一線狀圖案:

^((?:(?:(?:[^"'/\n]|/(?!/))*)(?("(?=(?:\\\\|\\"|[^"])*"))(?:"(?:\\\\|\\"|[^"])*")|(?('(?=(?:\\\\|\\'|[^'])*'))(?:'(?:\\\\|\\'|[^'])*')|(?(/)|.))))*) 

如果你想使用忽略模式空白選項,您可以使用此版本:

(?x) # Turn on the ignore white space option 
^(# Start the only capturing group 
    (?: # A non-capturing group to allow for repeating the logic 
     (?: # Capture either of the two options below 
      [^"'/\n] # Capture everything not a single quote, double quote, a slash, or a newline 
      | # OR 
      /(?!/) # Capture a slash not followed by a slash [slash an negative look-ahead slash] 
     )* # As many times as possible, even if none 
     (?(" # Start a conditional match for double-quoted strings 
       (?=(?:\\\\|\\"|[^"])*") # Followed by a properly closed double-quoted string 
      ) # Then 
      (?:"(?:\\\\|\\"|[^"])*") # Capture the whole double-quoted string 
      | # Otherwise 
      (?(' # Start a conditional match for single-quoted strings 
       (?=(?:\\\\|\\'|[^'])*') # Followed by a properly closed single-quoted string 
       ) # Then 
       (?:'(?:\\\\|\\'|[^'])*') # Capture the whole double-quoted string 
       | # Otherwise 
       (?([^/]) # If next character is not a slash 
       .) # Capture that character, it is either a single quote, or a double quote not part of a properly closed 
      ) # end the conditional match for single-quoted strings 
     ) # End the conditional match for double-quoted strings 
    )* # Close the repeating non-capturing group, capturing as many times as possible, even if none 
) # Close the only capturing group 

這使你的代碼來解釋這個怪物,這樣當其他人看着它時,或者在幾個月內你必須自己處理它時,就沒有WTF時刻。我認爲這些評論可以很好地解釋它,但隨意以任何方式改變它們。

如上所述,條件匹配分組的支持有限。它會失敗的一個地方是您在之前的評論中鏈接到的網站。由於您使用的是C#,因此我選擇在.NET Regex Tester中執行測試,該測試可以處理這些構造。它也包含一個很好的參考。鑑於正確的選擇,您可以測試以上任一版本,並進行實驗。考慮到它的複雜性,我建議在某處測試它,以對照來自文件的數據,以及任何你可以想象的邊緣病例和病理測試。

只是爲了兌換這個小小的模式,測試電子郵件地址的方式有一個更大的模式,即78列81行,並有幾十個字符可用。 (其中我不是建議使用,或任何其他正則表達式,測試電子郵件地址。工作錯誤的工具。)如果你想嚇倒你自己,請在ex-parrot網站上看看它。我沒有任何關係!

+0

感謝你的努力,但你的正則表達式並沒有把'qwe \「qwe」\\ asd'這樣的引號分隔出來,現在我要用'「(?> [^ \\\ n」] + | \\)*「|(\/\ /.*)'(https://regex101.com/r/GxcvJz/6)。我也看了鏈接。該正則表達式是一個怪物。再次感謝您的努力! – Crimson7

+0

我的錯誤。我用反斜槓代替正斜槓。您的解決方案完美運作另外它還可以節省我手動分離字符串和註釋的麻煩。萬分感謝! – Crimson7

+0

如果你發現一些不起作用的邊緣情況,請發表評論,以便我可以嘗試進一步調整。我認爲它可以捕捉所有的病例,甚至語法上無效的病例,除了配對引號。我打算將它保存在我的圖書館中,並且希望儘可能保持良好。 –

1

"[^"\\]*(?:\\[\W\w][^"\\]*)*"|(\/\/.*)

標誌:全球

匹配滿弦或評論。

第1組:評論。

因此,如果沒有評論,請用相同的匹配文本替換。否則,請在評論本身上做你的事情。

+0

它與[link](https://regex101.com/r/Nkftcf/3)相比如何?哪一個會更好? – Crimson7