Javaの正規表現の詳細な分析

メタキャラクタ

 

 

  1. 正規表現は、一致するものを検索し、特定のメタ文字を使用して、ルールに沿った文字列を置換します
  2. メタキャラクタ:通常の文字、文字の標準、(数量詞)文字を定義する文字を配置(文字境界)

正規表現エンジン

  1. 正規表現は、通常の記号式で書かれています
  • 正規表現構文解析のプログラムで、構文解析ツリー
  • そして、解析ツリーは、文字の一致に応じて正規表現エンジンの実行プログラム(ステートマシン)と連動して発生しました
  • 正規表現エンジンは、状態機械を確立するために使用されるアルゴリズムのコアセットであります
  • 概要
  • 正規表現=>パースツリー
  • マッチングのための木の正規表現エンジン= +> =ステート・マシンを解析>文字
  1. 現在、二つの方法で正規表現エンジンを実装
  • オートマトンDFA(決定性有限オートマトン、決定性有限オートマトン)
  • NFAオートマトン(非決定性有限オートマトン、非決定性有限オートマトン)
  1. 設定は、オートマトンDFA NFAオートマトンのコストよりもはるかに大きいですが、効率がDFAオートマトンNFAオートマトンよりも高く、
  • 正規表現エンジンとしてオートマトンDFA、時間複雑度はO(n)のマッチング場合、文字列の長さがnであると仮定すると
  • 、正規表現エンジンとしてNFAオートマトン、NFAオートマトン大枝の数とマッチング処理にバックトラック、状態の数は、NFA Sとすると
  • 時間の複雑さを一致させることはO(ナノ秒)であります
  1. より高度な機能をサポートしていますが、それらは独立したサブ表現の一致に基づいている利点NFA自動機
  • そのため、正規表現ライブラリを使用したプログラミング言語は、NFA自動機実装に基づいています

NFA自動機

マッチング処理

  1. NFA各文字の正規表現を読み、ターゲット文字列に一致するようにそれを取るために、自動的にチャンス
  2. 試合は、正規表現を変更するには、次の文字成功し、その逆は、次の文字列の一致を対象としていきます
テキスト= "aabcab" 
正規表現= "BC"
Javaの正規表現の詳細な分析

 

バックトラッキング

  1. マッチング処理では、より複雑な正規表現を用いて実装NFA自動機は、多くの場合、問題の原因となるバック
  2. バックトラックの多くは、このように、システムのパフォーマンス・オーバーヘッドをもたらし、CPUの占有を延長することになります
テキスト= "ABBC" 
正規表現= "AB {1,3} C"

最初の正規表現を読み取り、文字列が一致比較の最初の文字、ペアを一致

Javaの正規表現の詳細な分析

 

記号B {1,3} b及び第2の文字列が一致するように比較され、一致する第二の正規表現を読み取るが、B {1,3}は1〜3文字であり、NFAオートマトンは貪欲有します特徴は、それは次の正規表現に一致する文字cを読みません

Javaの正規表現の詳細な分析

 

使用列B {1,3}と4文字cが比較され、不一致が発見され、その後、バックトラッキングが発生し、読み出された4番目の文字列は、バック最初に文字c、ポインタに排出されます。 3つの文字位置B

Javaの正規表現の詳細な分析

 

バックトラッキングが発生した後、次の正規表現に一致する文字c、及び比較結果が一致C 4番目の文字列を読み取ります

Javaの正規表現の詳細な分析

 

バックトラックは避けてください

バックトラック避けてください:使用レイジーモードと排他モード

貪欲モード(貪欲)

  1. 一人で+を使用した場合、番号をマッチング?、*、{MIN、MAX}数量詞等、多くのコンテンツとして正規表現に一致します
  2. テキスト=「ABBC」、正規表現=「AB {1,3} c」は、マッチ障害が発生し、それがバックトラックを引き起こすであろう
  3. テキスト= "ABBBC"、正規表現= "AB {1,3} C"、マッチングは成功であります

レイジーモード(消極的)

  1. レイジー・モードでは、文字にマッチする正規表現は、マッチが成功した場合、それは文字列の残りの部分と一致していきます、できるだけ繰り返されます
  2. ?レイジーオープンモード、テキスト= "ABC" を使用して、正規表現は= "AB {1,3}?C"
  • 照合結果が「ABC」、第1のモードで、すなわち、マッチング文字bは、バックトラック問題を回避するために、最小のNFAオートマトンマッチング範囲を選択しています

独占(強欲)

  1. そして、排他モードと貪欲は、より多くのコンテンツとして試合を最大化しますが、最終的に一致しますが、一致を失敗し、問題が発生しないバックトラック
  2. 怠惰+ターンモード、テキスト= "ABBC"、正規表現= "AB {1,3} + BC" を使用
  • 結果は発生しない問題をバックトラック、不一致、試合の終わりです

コード

match("ab{1,3}c", "abbc"); // abbc,贪婪模式,产生回溯
match("ab{1,3}c", "abbbc"); // abbbc,贪婪模式,不产生回溯
match("ab{1,3}?", "abbbb"); // ab,懒惰模式,不产生回溯
match("ab{1,3}+bc", "abbc"); // null,独占模式,不产生回溯

正则表达式的优化

  1. 少用贪婪模式,多用独占模式(避免回溯)
  2. 减少分支选择,分支选择类型"(X|Y|Z)"的正则表达式会降低性能,尽量减少使用,如果一定要使用
  • 考虑选择的顺序,将比较常用的选择放在前面,使它们可以较快地被匹配
  • 提取共用模式,(abcd|abef) => ab(cd|ef)
  • 如果是简单的分支选择类型,可以用三次index代替(X|Y|Z)
  1. 减少捕获嵌套
  • 捕获组:把正则表达式中,子表达式匹配的内容保存到以数字编号或显式命名的数组中,一般一个()就是一个捕获组
  • 每个捕获组都有一个编号,编号0代表整个匹配到的内容
  • 非捕获组:参与匹配却不进行分组编号的捕获组,其表达式一般由(?:exp)组成
  • 减少不需要获取的分组,可以提高正则表达式的性能

捕获组

String text = "<input high=\"20\" weight=\"70\">test</input>";
String reg = "(<input.*?>)(.*?)(</input>)";
Pattern p = Pattern.compile(reg);
Matcher m = p.matcher(text);
while (m.find()) {
System.out.println(m.group(0));// 整个匹配到的内容
System.out.println(m.group(1));//(<input.*?>)
System.out.println(m.group(2));//(.*?)
System.out.println(m.group(3));//(</input>)
// 输出:
// <input high="20" weight="70">test</input>
// <input high="20" weight="70">
// test
// </input>
}

非捕获组

ストリング・テキスト= "<入力ハイ= \" 20 \ "重量= \ "70 \">テスト</入力>"。
文字列REG = ":(。*?)(?<。?入力*>)(:?</入力>)";
パターンp = Pattern.compile(REG)。
整合M = p.matcher(テキスト)。
一方、(m.find()){
System.out.printlnは(m.group(0)); //整个匹配到的内容
のSystem.out.println(m.group(1)); //(*。? )
//输出
// <入力ハイ= "20"重量= "70">テスト</入力>
//テスト
}

概要

パフォーマンステストを行うための前提の下で、あなたは正規表現を使用することができ、またはパフォーマンスの問題を回避するために、より多くを行うことはできません。

記事は、その後、ここでは最後に、私は正規表現が自分の理解を持って、パフォーマンステストであなたを願っています。これは、今日のパフォーマンス作品を完結します!

より多くのビデオソースの場合、面接の質問、Javaテクノロジー、書籍、その他の学習教材

私に従ってください!772 300 343プラスグループ得ることができます!

私たちは次の記事を参照して、小さなフレームでした!

おすすめ

転載: www.cnblogs.com/sevencutekk/p/11592465.html