簡體   English   中英

字符串操作與Regexps

[英]String manipulation vs Regexps

我們經常被告知Regexps很慢,應該盡可能避免。

), especially in PHP or Perl (maybe Java ) what is the limit , in which case can we consider string manipulation to be a better alternative? 但是,考慮到自己做一些字符串操作的開銷( ),特別是在PHPPerl (也許是Java )中有什么限制 ,在這種情況下我們可以考慮字符串操作是一個更好的選擇? 什么regexp特別是CPU貪心?

例如,對於以下內容,在C++JavaPHPPerl ,您會推薦什么?

正則表達式可能會更快:

  • s/abc/def/g或a ... while((i=index("abc",$x)>=0) ...$y .= substr()...基於解決方案?
  • s/(\\d)+/N/g或掃描算法

但是關於

  • 電子郵件驗證regexp?
  • s/((0|\\w)+?[xy]*[^xy]){2,7}/u/g

手工和特定算法不會更快(寫入時間更長)?

編輯

問題的關鍵是要確定哪種regexp最好通過字符串操作專門針對給定問題重寫?

EDIT2

一個常見的實現是Perl regexp。 例如在Perl -需要知道它們是如何實現的-什么樣的正則表達式的是要避免的,因為實現將使過程冗長和無效? 它可能不是一個復雜的正則表達式......

編輯2011年7月 (根據評論)

我並不是說所有正則表達式都很慢。 已知一些特定的正則表達式模式是緩慢的,這是由於它們的特定處理以及由於它們的實現。
例如,在最近的Perl / PHP實現中,已知的是相當緩慢 - 應該避免?
答案是從那些已經進行了自己的研究(剖析器......)的人那里得到的,他們能夠提供一些關於建議/要避免什么的一般指導。

誰說正則表達速度很慢? 至少在Perl中,它們往往是操縱字符串的首選方法。

正則表達式在電子郵件驗證等方面很糟糕,因為主題過於復雜,而不是因為它們很慢。 正確的電子郵件驗證正則表達式長度超過6000個字符,它甚至不處理所有情況(您必須首先刪除注釋)。

至少在Perl 5中,如果它有一個語法,它可能不應該用一個正則表達式進行解析。

如果正則表達式已經發展到無法再輕松維護的程度(請參閱上一個電子郵件驗證示例),或者性能分析顯示正則表達式是代碼的慢速組件,您還應該將正則表達式重寫為自定義函數。

您似乎關注正則表達式與自定義算法的速度,但在您證明它與分析器一起使用之前,這不是一個有效的問題。 以最易維護的方式編寫代碼。 如果正則表達式是明確的,那么使用正則表達式。 如果清除自定義算法,則使用自定義算法。 如果您發現在分析代碼后要么花費大量時間,那么就要開始尋找替代方案。

使用正則表達式操作文本的一個很好的特性是模式是高級的和聲明性的。 這為實現留下了相當大的優化空間,例如分解最長的公共前綴或使用Boyer-Moore來表示靜態字符串。 簡潔的符號使專家更快地閱讀。 我立刻明白了什么

if (s/^(.)//) {
  ...
}

正在做,而index($_, 0, 1) = ""看起來比較嘈雜。

正則表達式的重要考慮因素不是下限,而是上限 它是一個強大的工具,因此人們相信它能夠從XML,電子郵件地址或C ++程序中正確提取令牌,並且沒有意識到需要一個更強大的工具,如解析器。

對於非常特定的目的,正則表達式永遠不會比手工制作的算法快。 更糟糕的是,在PHP中,它們必須在第一次使用時進行編譯(之后使用緩存)。

但是,它們肯定更簡潔。 此外,編寫自定義算法通常比正則表達式慢,因為正則表達式引擎通常以更低級別的語言實現,調用函數的開銷更少等。

例如, preg_replace('/a/', 'b', $string)幾乎肯定比通過字符串在PHP中循環更快。 但這是執行時間的不斷懲罰,有時由於回溯,正則表達式可能會有更糟糕的漸近行為。

強烈建議您了解正則表達式的實現方式,以便您可以知道何時編寫低效的表達式。

一些正則表達式非常快,正則表達式和自定義解決方案之間的差異可以忽略不計(或者不值得任何人打擾)。

然而,正則表達式較慢的情況是發生過多的回溯 正則表達式從左到右解析,並且有可能以多種方式匹配文本。 因此,如果它們達到引擎意識到模式不匹配您的測試字符串的點,那么它可能會重新開始並嘗試以另一種方式匹配。 這種重復的回溯加起來並減慢了算法的速度。

通常可以重寫正則表達式以更好地執行。 但最終的性能是為特定任務編寫自己的優化解析器。 通過編寫自己的解析器,您可以從左到右進行解析,同時保持內存(或狀態)。 如果你在程序代碼中使用這種技術,你通常可以在一次通過中實現你正在尋找的效果而且沒有回溯的緩慢。

我在今年早些時候面臨這個決定。 事實上,手頭的任務是在正則表達式甚至可能的外邊緣。 最后我決定編寫自己的解析器,一個嵌入式下推自動機,這對於我試圖做的事情非常有效。 順便說一句,任務是構建一些可以解析正則表達式並為它們提供類似Intellisense的代碼提示的東西。

有點諷刺的是我沒有使用正則表達式來解析正則表達式,但是你可以在這里閱讀它背后的想法... http://blog.regexhero.net/2010/03/code-hinting-for-常規expressions.html

什么樣的正則表達式最好通過字符串操作專門針對給定問題重寫?

簡單。

  1. 確定是否需要重寫任何內容。
    (肯定的答案是每10000個腳本大約1個,大量文本解析,資源嚴重)
  2. 配置可能的解決方案。
  3. 使用一個適合您的特定問題

至於剩下的9999個案例,不要浪費你的時間處理這樣一個小問題,並使用你喜歡的任何東西。

每當你問自己這樣一個問題時,提醒自己默認情況下,在每個用戶請求中,所有額外優化和超快速的代碼都會被char解析為char非常有用。 沒有大腦破裂的regexps,沒有狡猾的字符串操縱,但只是舊的好挑選字符一個接一個。

正則表達並不慢。 但實現可能很慢,主要是因為它經常在每次使用時再次解釋和構建。 但是好的regexp庫允許你使用編譯版本。 它們非常快。

暫無
暫無

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

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