簡體   English   中英

何時值得在Java中使用RegEx?

[英]When would it be worth using RegEx in Java?

我正在寫一個小應用程序,它讀取一些輸入並根據該輸入做一些事情。

目前我正在尋找以“魔術”結尾的行,我會使用String的endsWith方法。 對於那些正在閱讀我的代碼的人來說,這是很清楚的。

另一種方法是創建一個Pattern並嘗試匹配以“magic”結尾的行。 這也很清楚,但我個人認為這是一種矯枉過正,因為我正在尋找的模式並不復雜。

你認為什么時候使用RegEx Java值得? 如果它的復雜性,你會如何個人定義什么是復雜的?

此外,是否有時候使用模式實際上比字符串操作更快?

編輯:我正在使用Java 6。

基本上:如果有一個非正則表達式操作可以一步完成你想要的操作,那么總是這樣做。

這不是關於性能,而是關於a)可讀性和b)編譯時安全性。 專用的非正則表達式版本通常比正則表達式版本更容易閱讀。 並且其中一個專門方法中的拼寫錯誤將無法編譯,而正則表達式中的拼寫錯誤將在運行時失敗。

將基於Regex的解決方案與非Regex-base解決方案進行比較

String s = "Magic_Carpet_Ride";

s.startsWith("Magic");   // non-regex
s.matches("Magic.*");    // regex

s.contains("Carpet");    // non-regex
s.matches(".*Carpet.*"); // regex

s.endsWith("Ride");      // non-regex
s.matches(".*Ride");     // regex

在所有這些情況下,這是一個明智的選擇:使用非正則表達式版本。

但是當事情變得更復雜時,它取決於。 我猜我在以下情況下仍會堅持使用非正則表達式,但很多人不會:

// Test whether a string ends with "magic" in any case,
// followed by optional white space
s.toLowerCase().trim().endsWith("magic"); // non-regex, 3 calls
s.matches(".*(?i:magic)\\s*");            // regex, 1 call, but ugly

並回應RegexesCanCertainlyBeEasierToReadThanMultipleFunctionCallsToDoTheSameThing

我仍然認為非正則表達式版本更具可讀性,但我會這樣寫:

s.toLowerCase()
 .trim()
 .endsWith("magic");

完全不同,不是嗎?

當對String類的正常操作不足以從String中優雅地獲得所需內容時,您將使用Regex。

這種情況的一個很好的指標是,當您開始拆分,然后拆分這些結果,然后拆分這些結果。 代碼變得笨拙。 兩行Pattern / Regex代碼可以清理它,整齊地包裹在一個單元測試的方法中....

任何可以使用正則表達式完成的操作也可以手動編碼。

使用正則表達式:

  1. 手動完成它將需要更多的努力而沒有太多的好處。
  2. 您可以輕松地為您的任務提出正則表達式。

如果符合以下條件, 請勿使用正則表

  1. 這樣做很容易,就像你的例子一樣。
  2. 您正在解析的字符串不適合正則表達式。 (習慣上鏈接到這個問題

我認為你最好使用endsWith 除非您的要求發生變化,否則更簡單易懂。 可能也會表現得更快。

如果有更多的復雜性,例如你想要匹配“魔法”,“majik”,但不是“Magic”或“Majik”;或者你想匹配“魔法”后跟一個空格然后1個單詞如“......魔術勺”但不是“......魔術湯匙”,那么我認為RegEx將是一個更好的方式。

當您考慮計算能力和為此目的生成代碼所需的智能時,使用RegEx可以更好地完成生成大量對象的任何復雜解析。 如果您有一個方便的RegEx專家,它幾乎總是值得的,因為模式可以很容易地調整以適應業務規則更改而無需重大循環重構,如果您使用純java來執行RegEx所做的一些復雜事情,則可能需要這些重構。

有一種說法:

有些人在面對問題時會想“我知道,我會使用正則表達式”。 現在他們有兩個問題 鏈接 )。

對於一個簡單的測試,我會像你一樣完成。 如果你發現它變得越來越復雜,那么只有在沒有其他方法時才會考慮正則表達式。

如果您的基本行結尾每次都相同,例如“魔術”,那么您最好使用endsWith。

但是,如果您的行具有相同的基數,但可以具有多個值,例如:

<string> <number> <string> <string> <number>

字符串和數字可以是任何東西,你最好使用RegEx。

你的行總是以字符串結尾,但你不知道那個字符串是什么。

如果它像endsWith,startsWith或contains一樣簡單,那么你應該使用這些函數。 如果您正在處理更多“復雜”字符串並且想要從這些字符串中提取信息,則可以使用regexp / matchers。

如果您有類似“commandToRetrieve someNumericArgs someStringArgs someOptionalArgs”之類的東西,那么regexp將大大減輕您的任務:)

如果我有一個更簡單的方法,我永遠不會在java中使用正則表達式,就像在這種情況下的endsWith方法。 java中的正則表達式一樣丑陋,可能除了String上的match方法之外。

通常,避免使用正則表達式可以使您的核心對其他程序員更具可讀性和易用性。 反之亦然,復雜的正則表達甚至可能會讓那些經驗最豐富的黑客感到困惑。

至於性能問題:只是簡介。 特別是在java中。

當您知道輸入的格式但我不一定確定格式化輸入的 (或可能的值)時,我建議使用正則表達式。

我所說的,如果你的輸入都是以“魔術”結尾,那么String.endsWith()工作正常(看到你知道你的可能輸入值將以“魔法”結束)。

如果您的格式為RFC 5322格式 ,則無法清楚地說明所有電子郵件地址都以.com結尾,因此您可以創建符合RFC 5322標准的正則表達式進行驗證。

簡而言之,如果您知道輸入數據的格式結構但不確切知道可以接收的值(或可能的值),請使用正則表達式進行驗證。

如果您熟悉regexp的工作原理,您很快就會發現使用regexp可以輕松解決許多問題。

我個人認為使用java String操作,如果這很容易,但如果你開始拆分字符串並再次對它們進行子串,我會開始考慮正則表達式。

而且,如果你使用正則表達式,為什么要停在線上。 通過配置正則表達式,您可以輕松地在一個正則表達式中讀取整個文件(Pattern.DOTALL作為Pattern.compile的參數,並且您的正則表達式不會在換行符中結束)。 我將它與Apache Commons IOUtils.toString()方法相結合,你可以得到一些非常強大的功能來快速完成。

如果需要,我甚至會帶出一個正則表達式來解析一些xml。 (例如在單元測試中,我想檢查xml中是否存在某些元素)。

例如,從我的一些單元測試中:

Pattern pattern = Pattern.compile(
                "<Monitor caption=\"(.+?)\".*?category=\"(.+?)\".*?>"
                + ".*?<Summary.*?>.+?</Summary>"
                + ".*?<Configuration.*?>(.+?)</Configuration>"
                + ".*?<CfgData.*?>(.+?)</CfgData>", Pattern.DOTALL);

這將匹配此xml中的所有段,並選擇我想要進行一些子匹配的一些段。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM