49

次のような技術的な文字列があります。

"The thing P1 must connect to the J236 thing in the Foo position."

P1大文字のみの単語 (つまり、 hereと)を正規表現で照合したいと思いますJ236。問題は、1文字の単語の場合、文の最初の文字を一致させたくないことです。

例:

"A thing P1 must connect ..." 

P1とではなくA、のみが必要ですP1。そうすることで、本当の「単語」( のような)を見逃す可能性があることを知っていますが、それを受け入れることが"X must connect to Y"できます。

さらに、文がすべて大文字の場合、大文字の単語を一致させたくありません。

例:

"THING P1 MUST CONNECT TO X2."

もちろん、理想的には、専門用語P1X2ここを一致させたいのですが、すべて大文字の文に「隠されている」ため、これらの専門用語には特定のパターンがないため、不可能です。私のファイルでは、すべて大文字の文はそれほど頻繁に使用されないため、この場合も問題なく使用できます。

ありがとう!

4

6 に答える 6

78

これは、使用している RegEx の「フレーバー」によってある程度異なります。\b以下は、単語境界に使用する .NET RegEx に基づいています。最後の例では、否定的なルックアラウンド(?<!)(?!)非キャプチャ括弧も使用しています(?:)

ただし、基本的には、用語に常に少なくとも 1 つの大文字とそれに続く少なくとも 1 つの数字が含まれている場合は、次のように使用できます。

\b[A-Z]+[0-9]+\b

すべて大文字と数字の場合 (合計は 2 以上である必要があります):

\b[A-Z0-9]{2,}\b

すべて大文字と数字で、少なくとも 1 つの文字で始まる場合:

\b[A-Z][A-Z0-9]+\b

おじいちゃん、大文字と数字の任意の組み合わせを含むが、行頭の単一文字ではなく、すべて大文字の行の一部ではないアイテムを返します。

(?:(?<!^)[A-Z]\b|(?<!^[A-Z0-9 ]*)\b[A-Z0-9]+\b(?![A-Z0-9 ]$))

壊す:

正規表現は で始まり(?:ます。は次の?:ことを意味します -- 以下は括弧内にありますが、結果をキャプチャすることに興味はありません。これは「非キャプチャ括弧」と呼ばれます。ここでは、代替を使用しているため、括弧を使用しています (以下を参照)。

非キャプチャ括弧内には、パイプ記号 で区切られた 2 つの別個の節があります|。これは交替です。「または」のようなものです。正規表現は、最初の式または2 番目の式と一致できます。ここでの 2 つのケースは、「これは行の最初の単語ですか」または「その他すべて」です。これは、行の先頭にある 1 文字の単語を除外するという特別な要件があるためです。

それでは、交代の各表現を見てみましょう。

最初の式は次のとおり(?<!^)[A-Z]\bです。ここでの主要な句は[A-Z]\bで、これは任意の 1 つの大文字の後に句読点、空白、改行などの単語境界が続くものです。その前の部分(?<!^)は、「否定後読み」です。これはゼロ幅のアサーションです。つまり、一致の一部として文字を「消費」しません。ここでそれを理解することはあまり重要ではありません。.NET での否定後読みの構文は次のとおりです。x(?<!x)は、主節の前に存在してはならない式です。ここで、その表現は単純に 、または行頭であるため、交代のこちら側は「行頭にない単一の大文字からなる任意の単語」と解釈されます。^

さて、行の先頭にない 1 文字の大文字の単語を照合しています。すべての数字と大文字で構成される単語を一致させる必要があります。

これは、alternation: の 2 番目の式の比較的小さな部分によって処理されます\b[A-Z0-9]+\b\bs は単語の境界を表し、 は 1 つ以上の数字と大文字を一緒に一致[A-Z0-9]+させます。

式の残りの部分は、他のルックアラウンドで構成されています。(?<!^[A-Z0-9 ]*)は別の否定的な後読みで、式は^[A-Z0-9 ]*です。これは、先行するものはすべて大文字と数字であってはならないことを意味します。

2 番目の(?![A-Z0-9 ]$)ルックアラウンドは、否定先読みです。これは、後に続くすべてが大文字と数字であってはならないことを意味します。

したがって、全体として、すべて大文字と数字の単語をキャプチャし、行頭から 1 文字の大文字を除外し、すべて大文字の行からすべてを除外します。

ここには、2 番目の代替表現のルックアラウンドが独立して機能するという点で、少なくとも 1 つの弱点があります。したがって、「A P1 should connect to the J9」のような文は J9 と一致しますが、P1 とは一致しません。

この問題を回避することは可能ですが、正規表現の長さがほぼ 3 倍になります。単一の正規表現で多くのことを行おうとすることは、正当化されることはほとんどありません。作業を複数の正規表現に分割するか、選択したプログラミング言語で正規表現と標準の文字列処理コマンドを組み合わせた方がよいでしょう。

于 2011-01-04T20:59:56.180 に答える
5

なぜ1つのモンスター正規表現でこれを行う必要があるのですか? 実際のコードを使用してこれらのルールの一部を実装できます。そうすることで、後でこれらの要件が変更された場合に変更するのがはるかに簡単になります。

例えば:

if(/^[A-Z0-9\s]*$/)
    # sentence is all uppercase, so just fail out
    return 0;

# Carry on with matching uppercase terms
于 2011-01-04T21:00:41.157 に答える
5

最初にこの正規表現を実行して、行がすべて大文字かどうかを確認できます。

^[A-Z \d\W]+$

次のような行の場合にのみ一致しますTHING P1 MUST CONNECT TO X2.

それ以外の場合は、これで個々の大文字のフレーズを引き出すことができるはずです:

[A-Z][A-Z\d]+

これは、「P1」と「J236」に一致する必要がありますThe thing P1 must connect to the J236 thing in the Foo position.

于 2011-01-04T21:12:24.933 に答える
4

[AZ] や [0-9] のようなことはしないでください。代わりに \p{Lu} と \d を実行してください。もちろん、これは perl ベースの正規表現にも有効です。これには Java が含まれます。

巨大な正規表現を作成しないことをお勧めします。まず文章を文章に分割します。次に、それをトークン化します (単語に分割します)。正規表現を使用して、各トークン/単語を確認します。文の最初のトークンをスキップします。事前にすべてのトークンが大文字かどうかを確認し、大文字の場合は文全体をスキップするか、この場合は正規表現を変更してください。

于 2013-02-12T16:24:16.297 に答える
3

私は決して正規表現の第一人者ではありません。しかし、試してください:

<[A-Z0-9][A-Z0-9]+>

<           start of word
[A-Z0-9]    one character
[A-Z0-9]+   and one or more of them
>           end of word

大文字のセンテンス全体のボーナス ポイントを求めるつもりはありません。へへ

于 2011-01-04T21:07:30.343 に答える
2

最初のケースでは、'[[:blank:]]+[A-Z0-9]+[[:blank:]]+' を使用できます。例:

echo "モノ P1 は Foo の位置で J236 モノに接続する必要があります" | grep -oE '[[:空白:]]+[A-Z0-9]+[[:空白:]]+'

2番目のケースでは、正規表現ではなく、他の何かを使用する必要があるかもしれません。おそらく、専門用語の辞書を備えたスクリプトです...

乾杯、フェルナンド

于 2011-01-04T21:00:26.487 に答える