2016-11-24 36 views
1

正しく解析するのに苦労しています。テキストには多くのバリエーションがあります。理想的には、私はこれをPythonで行いたいと思いますが、どの言語でも動作します。正規表現の解析文字列

例文字列:私は希望

  • "if magic code is 543, and type is 5642, 912342, or 7425, type has to have a period. EX: 02-15-99"
  • "If Magic Code is 722, 43, or 643256 and types is 43234, 5356, and 2112, type has to start with period."
  • "if magic code is 4542 it is not valid in type."
  • "if magic code is 532 and date is within 10 years from current data, and the type is 43, the type must begin with law number."

結果:

  • [543] [5642, 912342, 7425][type has to have a period.]
  • [722, 43, 643256][3234, 5356, and 2112][type has to start with period.]
  • [4542][it is not valid in type.]
  • [532][43][the type must begin with law number.]

あり、他のバリエーションがありますが、あなたはコンセプトを参照してください。申し訳ありませんが、正規表現はあまりよくありません。

+0

あなたがつかむために探している文字列の部分とのルールは何ですか? – idjaw

+0

私が望む結果は投稿にあります。 –

+2

*テキストにバリエーションがたくさんあります。* - 自然言語の認識が必要で、正規表現は必要ないようです。どのように@Lukeallthingsspatial –

答えて

1

まあ...これはあなたが尋ねたことです。しかし、それは非常に醜い、あなたが提供した例に非常に特有です。私はそれが実際のデータファイルに対して失敗すると思う。

この種の解析ジョブに直面すると、問題を解決する方法の1つは、いくつかの予備的なクリーンアップによって入力データを実行し、可能であればテキストを単純化し合理化することです。たとえば、整数のリストの異なるフレーバーを扱うことは迷惑であり、正規表現はより複雑になります。不必要なカンマの間のコンマを削除して、ターミナル「or-and」を削除できれば、正規表現ははるかに簡単になります。そのようなクリーンアップが完了したら、必要なビットを抽出するために1つ以上の正規表現を適用することができます。場合によっては、主要な正規表現を満たさないアウトライヤーの数は、特定のルックアップまたはハードコードされた特別なケースのルールで処理できます。

import re 

lines = [ 
    "if magic code is 543, and type is 5642, 912342, or 7425, type has to have a period. EX: 02-15-99", 
    "If Magic Code is 722, 43, or 643256 and types is 43234, 5356, and 2112, type has to start with period.", 
    "if magic code is 4542 it is not valid in type.", 
    "if magic code is 532 and date is within 10 years from current data, and the type is 43, the type must begin with law number.", 
] 

mcs_rgx = re.compile(r'magic code is (\d+ (or|and) \d+|\d+(, \d+)*,? (or|and) \d+|\d+)', re.IGNORECASE) 
types_rgx = re.compile(r'types? is (\d+ (or|and) \d+|\d+(, \d+)*,? (or|and) \d+|\d+)', re.IGNORECASE) 
rest_rgx1 = re.compile(r'(type (has|must).+)') 
rest_rgx2 = re.compile(r'.+\d(.+)') 
nums_rgx = re.compile(r'\d+') 

for line in lines: 

    m = mcs_rgx.search(line) 
    if m: 
     mcs_text = m.group(1) 
     mcs = map(int, nums_rgx.findall(mcs_text)) 
    else: 
     mcs = [] 

    m = types_rgx.search(line) 
    if m: 
     types_text = m.group(1) 
     types = map(int, nums_rgx.findall(types_text)) 
    else: 
     types = [] 

    m = rest_rgx1.search(line) 
    if m: 
     rest = [m.group(1)] 
    else: 
     m = rest_rgx2.search(line) 
     if m: 
      rest = [m.group(1)] 
     else: 
      rest = [''] 

    print mcs, types, rest 

出力:

[543] [5642, 912342, 7425] ['type has to have a period. EX: 02-15-99'] 
[722, 43, 643256] [43234, 5356, 2112] ['type has to start with period.'] 
[4542] [] [' it is not valid in type.'] 
[532] [43] ['type must begin with law number.'] 
+0

正規表現はどうやってうまくいったのですか?投稿していただきありがとうございます。正規表現を学ぶ単なる死人の提案はありますか? –

+0

@Lukeallthingsspatialほとんどの練習。 Jeffrey Friedlの "Mastering regular expressions"はとても良いですが、他にも多くのオンラインチュートリアルがあります。注目すべき重要なもの:目標は正規表現を学ぶことではありません。むしろ、それはテキスト解析に熟練することです。これは広範な努力であり、正規表現はいくつかのツールのうちの1つにすぎません。テキスト解析では、あなたのポイント、すなわちテキストのどの部分がテキストをより簡単な部分に分解できるようにする共通の点(話すべき「規則」)であるかに焦点を当てる必要があります。がんばろう! – FMc

0

ここでは、単一の正規表現を加えた事実の後にいくつかのクリーニングアップとソリューションです。これはあなたのすべての例で有効ですが、コメントに記載されているように、文章がこれよりはるかに異なる場合は、正規表現以外のオプションを探さなければなりません。

import re 

sentences = ["if magic code is 543, and type is 5642, 912342, or 7425, type has to have a period. EX: 02-15-99", 
      "If Magic Code is 722, 43, or 643256 and types is 43234, 5356, and 2112, type has to start with period.", 
      "if magic code is 4542 it is not valid in type.", 
      "if magic code is 532 and date is within 10 years from current data, and the type is 43, the type must begin with law number."] 

pat = '(?i)^if\smagic\scode\sis\s(\d+(?:,?\s(?:\d+|or))*)(?:.*types?\sis\s(\d+(?:,?\s(?:\d+|or|and))*,)(.*\.)|(.*\.))' 

find_ints = lambda s: [int(d) for d in re.findall('\d+', s)] 

matches = [[g for g in re.match(pat,s).groups() if g] for s in sentences] 

results = [[find_ints(m) for m in match[:-1]]+[[match[-1].strip()]] for match in matches] 

そして、あなたはあなたの例のようにきれいに印刷されたものが必要な場合:

for r in results: 
    print(*r, sep='') 
関連する問題