乱雑:
手始めに、元の PHP ステートメント:
$itemFullName = preg_replace("@^\b(([a-zA-Z]{1,3})?[0-9]{1,2}(\.|\-|X)[0-9]{1,2}(\s|\.|\-)?(X|x)?\s?[0-9]{1,3}\.?(([0-9]{1,3})?(X[0-9]{1,3})|(\s[0-9]\/[0-9]|\/[0-9]{1,3}))?(\s\#[0-9]{1,3}\/[0-9]{1,3})?)\s@", ' ', $itemFullName, -1, $sum);
次のようなコメントを付けてフリースペース モードで記述すると、はるかに読みやすく (そして保守しやすく) なります。
几帳面:
$itemFullName = preg_replace("/(?#!php re_item_tidy Rev:20180207_0700)
^ # Anchor to start of string.
\b # String must begin with a word char.
( # $1: Unnecessary group.
([a-zA-Z]{1,3})? # $2: Optional 1-3 alphas.
[0-9]{1,2} # 1-2 decimal digits.
(\.|\-|X) # $3: Either a dot, hyphen or X.
[0-9]{1,2} # One or two decimal digits.
(\s|\.|\-)? # $4: Optional whitespace, dot or hyphen.
(X|x)? # $5: Optional X or x.
\s?[0-9]{1,3}\.? # Optional whitespace, 1-3 digits, optional dot.
( # $6: Optional ??? from 2 alternatives.
([0-9]{1,3})? # Either a1of2 $7: Optional 1-3 digits.
(X[0-9]{1,3}) # $8: X and 1-3 digits.
| ( # Or a2of2 $9: one ??? from 2 alternatives.
\s[0-9]\/[0-9] # Either a1of2.
| \/[0-9]{1,3} # Or a2of2.
) # End $9: one ??? from 2 alternatives.
)? # End $6: optional ??? from 2 alternatives.
( # $10: Optional sequence.
\s\#[0-9]{1,3} # whitespace, hash, 1-3 digits.
\/[0-9]{1,3} # Forward slash, 1-3 digits.
)? # End $10: Optional sequence
) # End $1: Unnecessary group.
\s # End with a single whitespace char.
/x", ' ', $itemFullName, -1, $sum);
批評:
この正規表現は、パフォーマンス的には悪くありません。最初に文字列アンカーの開始があり、一致しない文字列に対してすぐに失敗するのに役立ちます。また、後戻りの問題もありません。ただし、いくつかの小さな改善点があります。
- 代替には 3 つのグループがあり、各代替は 1 文字のみで構成されます。これらの各代替は、単純な文字クラスに置き換えることができます。
- 10 個のキャプチャ グループがありますが、preg_replace はキャプチャされたデータをまったく使用しません。これらのキャプチャ グループは、非キャプチャに変更できます。
- 簡単に削除できる不要なグループがいくつかあります。
- グループ 2:
([a-zA-Z]{1,3})?
は、次のように簡単に記述できます[a-zA-Z]{0,3}
。グループ 7 は同様の構造を持っています。
- 先頭の
\b
単語境界は不要です。
- PHP では、単一引用符で囲まれた文字列で正規表現パターンを囲むのが最善です。二重引用符で囲まれた文字列には、エスケープする必要がある多くのメタ文字があります。一重引用符文字列には、一重引用符とバックスラッシュの 2 つしかありません。
- 不必要にエスケープされたスラッシュがいくつかあります。
$sum
によって行われる置換の数をカウントするために変数を使用していることにも注意してくださいpreg_replace()
。パターンの先頭に文字列アンカーの開始があるため、複数行修飾子^
を指定していないため、置換は 1 つしかありません。'm'
実際に複数の置換を実行したい (そしてそれらを で数えたい) と想定しているので、修飾子$sum
を追加しました。'm'
これらの変更を組み込んだ改良版を次に示します。
整理整頓:
$itemFullName = preg_replace('%(?#!php/m re_item_tidier Rev:20180207_0700)
^ # Anchor to start of string.
[a-zA-Z]{0,3} # Optional 1-3 alphas.
[0-9]{1,2} # 1-2 decimal digits.
[.X-] # Either a dot, hyphen or X.
[0-9]{1,2} # One or two decimal digits.
[\s.-]? # Optional whitespace, dot or hyphen.
[Xx]? # Optional X or x.
\s?[0-9]{1,3}\.? # Optional whitespace, 1-3 digits, optional dot.
(?: # Optional ??? from 2 alternatives.
[0-9]{0,3} # Either a1of2: Optional 1-3 digits
X[0-9]{1,3} # followed by X and 1-3 digits.
| (?: # Or a2of2: One ??? from 2 alternatives.
\s[0-9]/[0-9] # Either a1of2.
| /[0-9]{1,3} # Or a2of2.
) # End one ??? from 2 alternatives.
)? # End optional ??? from 2 alternatives.
(?: # Optional sequence.
\s\#[0-9]{1,3} # whitespace, hash, 1-3 digits.
/[0-9]{1,3} # Forward slash, 1-3 digits.
)? # End optional sequence
\s # End with a single whitespace char.
%xm', ' ', $itemFullName, -1, $sum);
ただし、パフォーマンスが向上したとしても、あまり見られないと思います。元の正規表現はかなり優れています。パフォーマンスの問題は、おそらくプログラムの他の側面から発生しています。
お役に立てれば。
編集 2018-02-07 :余分な二重引用符を削除し、正規表現のシバンを追加しました。