2

php正規表現を記述して、テキストから1つの数字とスペースを含めることもできる大文字の文字列を検索したいと思います。

たとえば、このテキストから"some text to contain EXAM PL E 7STRING uppercase word"文字列を取得したい- EXAM PL E 7STRING

見つかった文字列は大文字でのみ開始および終了する必要がありますが、大文字を使用しない場合は、1つの数字とスペースを含めることもできます(必ずしもそうとは限りません)。したがって、正規表現はこれらのパターンのいずれかに一致する必要があります

1) EXAMPLESTRING               - just uppercase string
2) EXAMP4LESTRING              - with number
3) EXAMPLES TRING              - with space
4) EXAM PL E STRING            - with more than one spaces
5) EXAMP LE4STRING             - with number and space
6) EXAMP LE 4ST RI NG          - with number and spaces 

全長の文字列は4文字以上である必要があります

最初の4つのパターンを見つけることができるこの正規表現'/[A-Z]{1,}([A-Z\s]{2,}|\d?)[A-Z]{1,}/'を作成しましたが、最後の2つのパターンにも一致することがわかりません。

ありがとう

4

2 に答える 2

5

先読みと呼ばれる巧妙なトリックがあります。現在の位置の後に何が続いているかをチェックするだけです。これは、複数の条件をチェックするために使用できます。

'/(?<![A-Z])(?=(?:[A-Z][\s\d]*){3}[A-Z])(?!(?:[A-Z\s]*\d){2})[A-Z][A-Z\s\d]*[A-Z]/'

最初のルックアラウンドは実際にはルックビハインドであり、前の大文字がないことを確認します。これは、とにかく一致に失敗する文字列のほんの少しのスピードアップです。2番目のルックアラウンド(先読み)は、少なくとも4文字あることを確認します。3つ目は、2桁がないことを確認します。残りは、大文字で開始および終了する、許可された文字の文字列と一致します。

2桁の場合、これはまったく一致しないことに注意してください(2桁目までのすべてを一致させるのではなく)。このような場合に一致さたい場合は、代わりに「1桁」のルールを実際の一致に組み込むことができます。

'/(?<![A-Z])(?=(?:[A-Z][\s\d]*){3}[A-Z])[A-Z][A-Z\s]*\d?[A-Z\s]*[A-Z]/'

編集:

Ωmegaが指摘したように、2桁目の前の文字が4文字未満の場合、それ以降は問題が発生します。2桁目の前に4文字以上あるというアサーションが必要なため、これは実際には非常に困難です。これらの4文字の最初の桁がどこにあるかわからないため、考えられるすべての位置を確認する必要があります。このために、私は先読みを完全に廃止し、3つの異なる選択肢を提供するだけです。(一致しないパーツの最適化として、後読みを維持します。)

'/(?<![A-Z])[A-Z]\s*(?:\d\s*[A-Z]\s*[A-Z]|[A-Z]\s*\d\s*[A-Z]|[A-Z]\s*[A-Z][A-Z\s]*\d?)[A-Z\s]*[A-Z]/'

またはここにコメントを追加します:

'/
(?<!         # negative lookbehind
    [A-Z]    # current position is not preceded by a letter
)            # end of lookbehind
[A-Z]        # match has to start with uppercase letter
\s*          # optional spaces after first letter
(?:          # subpattern for possible digit positions
    \d\s*[A-Z]\s*[A-Z]
             # digit comes after first letter, we need two more letters before last one
|            # OR
    [A-Z]\s*\d\s*[A-Z]
             # digit comes after second letter, we need one more letter before last one
|            # OR
    [A-Z]\s*[A-Z][A-Z\s]*\d?
             # digit comes after third letter, or later, or not at all
)            # end of subpattern for possible digit positions
[A-Z\s]*     # arbitrary amount of further letters and whitespace
[A-Z]        # match has to end with uppercase letter
/x'

これにより、Ωmegaの長いテスト入力でも同じ結果が得られます。

于 2012-11-09T13:50:11.977 に答える
2

正規表現パターンを使用することをお勧めします

[A-Z][ ]*(\d)?(?(1)(?:[ ]*[A-Z]){3,}|[A-Z][ ]*(\d)?(?(2)(?:[ ]*[A-Z]){2,}|[A-Z][ ]*(\d)?(?(3)(?:[ ]*[A-Z]){2,}|[A-Z][ ]*(?:\d|(?:[ ]*[A-Z])+[ ]*\d?))))(?:[ ]*[A-Z])*

このデモを参照してください)。

[A-Z][ ]*(?:\d(?:[ ]*[A-Z]){2}|[A-Z][ ]*\d[ ]*[A-Z]|(?:[A-Z][ ]*){2,}\d?)[A-Z ]*[A-Z]

このデモを参照してください)

于 2012-11-09T14:02:02.517 に答える