0

これらは、アドレスで許可しない文字列です。

"PO BOX","P0 DRAWER","POSTOFFICE", " PO ", " BOX ",
 "C/O","C.O."," ICO "," C/O "," C\0 ","C/0","P O BOX",
 "P 0 BOX","P 0 B0X","P0 B0X","P0 BOX","P0BOX","P0B0X",
 "POBX","P0BX","POBOX","P.0.","P.O","P O "," P 0 ",
 "P.O.BOX","P.O.B","POB ","P0B","P 0 B","P O B",
 " CARE ","IN CARE"," APO "," CPO "," UPO ", "GENDEL",
 "GEN DEL", "GENDELIVERY","GEN DELIVERY","GENERALDEL",
 "GENERAL DEL","GENERALDELIVERY","GENERAL DELIVERY"

正規表現を作成しました: この表現は POBOx 部分のみを検証します – アドレス フィールドに上記のすべての文字列を許可しないように修正してください

"([\\w\\s*\\W]*((P(O|OST)?.?\\s*((O(FF(ICE)?)?)?.?\\s*(B(IN|OX|.?))|B(IN|OX))+))[\\w\\s*\\W]*)+
|([\\w\\s*\\W]* (IN \s*(CARE)?\\s*)|\s*[\\w\\s*\\W]*((.?(APO)?|.?(cPO)?|.?(uPO))?.?\s*) [\\w\\s*\\W]*|([\\w\\s*\\W]*(GEN(ERAL)?)?.?\s*(DEL(IVERY)?)?.?\s* [\\w\\s*\\W]*))";
4

3 に答える 3

2

アドレス文字列に制限されたフレーズが含まれているかどうかを確認しようとしていると思います。

単一の正規表現でこれを行わないでください。

1 つの大規模な正規表現一致クエリを実行すると、正規表現を作成するために何をしたかを理解するのが難しくなり、さらに制限が表示された場合に拡張するのが難しくなり、一般的にコード プラクティスが適切ではなくなります。


これは(うまくいけば)より健全なアプローチです:

public static final String RESTRICTIONS[] = { " P[0O] ", " B[0O]X ", "etc, etc" };

public static boolean containsRestrictions(String testString) {
    for (String expression : RESTRICTIONS) {
        Matcher restriction = Pattern.compile(expression).matcher(testString);
        if (restriction.find())
            return true;
    }
    return false;
}

あなたはまだ正規表現マッチングを行っているので、あなたの凝ったおかしな正規表現を制限リストに入れることができますが、単純な古い文字列でも機能します. これで、可能性のあるすべてのケースに対して巨大な正規表現を検証する代わりに、個々の正規表現のそれぞれが機能することを検証するだけで済みます。新しい制限を追加したい場合は、リストに追加してください。あなたが本当に好きなら、構成ファイルから制限をロードするか、Spring を使用してそれを注入することができます。これにより、厄介な製品の人々は、一連のコードに触れることなくアドレス制限を追加できます。


編集:これをさらに読みやすくし、本当にやりたいことを行う(空白を使用して他の文字列から区切られた文字列を制限する)には、制限から正規表現を完全に削除し、メソッドで基本的なマッチング作業を行うことができます。

// No regexes here, just words you wanna restrict
public static final String RESTRICTIONS[] = { "PO", "PO BOX", "etc, etc" };

public static boolean containsRestrictions(String testString) {
    for (String word : RESTRICTIONS) {
        String expression = "(^|\\s)" + word + "(\\s|$)";
        Matcher restriction = Pattern.compile(expression).matcher(testString);
        if (restriction.find())
            return true;
    }
    return false;
}
于 2013-09-11T18:33:18.810 に答える
1

では、プロのように部分文字列を検索したいですか? この種の問題を解決するAho Corasick アルゴリズムを使用することをお勧めします。

セールスポイント:

これは、入力テキスト内の文字列 (「辞書」) の有限セットの要素を見つける一種の辞書照合アルゴリズムです。すべてのパターンに同時に一致します。

幸いなことに、Java 実装が存在します。ここで入手できます。

使用方法は次のとおりです。

// this is the part you have to do only once

AhoCorasick tree = new AhoCorasick(); 

String[] terms = {"PO BOX","P0 DRAWER",...};

for (int i = 0; i < terms.length; i++) {
     tree.add(terms[i].getBytes(), terms[i]); 
}
tree.prepare();



// here comes the part you use for every address you want to check

String text = "The ga3 mutant of Arabidopsis is a gibberellin-responsive. In UPO, that is...";

boolean restrictedWordFound = false;

@SuppressWarnings("unchecked")
Iterator<SearchResult> search = (Iterator<SearchResult>)tree.search(text.getBytes());

if(search.hasNext()) {
    restrictedWordFound = true;
}

一致が見つかった場合はrestrictedWordFoundtrue になります。

注:この検索で​​は大文字と小文字が区別されます。文字列はすべて大文字であるため、最初にアドレスを一時的な大文字のバリアントに変換し、それに対してマッチングを使用することをお勧めします。そうすれば、考えられるすべての組み合わせをカバーできます。

私のテストから、Aho Corasick は正規表現ベースの検索よりも高速であり、ほとんどの場合、containsおよび他の文字列ベースのメソッドを使用した単純な文字列検索よりも高速です。さらに多くのフィルター ワードを追加できます。Aho Corasick は行くべき道です。

于 2013-09-12T08:51:09.287 に答える
0

このような複雑な正規表現を使用する代わりに、次のように述べることができます: 正規表現:

"PO BOX|P0 DRAWER|POSTOFFICE| PO | BOX |C/O|C.O.| ICO | C/O | C\0 |C/0|P O BOX|P 0 BOX|P 0 B0X|P0 B0X|P0 BOX|P0BOX|P0B0X|POBX|P0BX|POBOX|P.0.|P.O|P O | P 0 |P.O.BOX|P.O.B|POB |P0B|P 0 B|P O B| CARE |IN CARE| APO | CPO | UPO |GENDEL|GEN DEL|GENDELIVERY|GEN DELIVERY|GENERALDEL|GENERAL DEL|GENERALDELIVERY|GENERAL DELIVERY"

そして、答えを否定します。

正規表現を ( でJava) コンパイルすると、結果のメカニズムがより効率的になります。(Java は DFA の最小化を使用します)。

于 2013-09-11T18:24:41.160 に答える