4

Pythonのre -moduleを使用していくつかの文字列を一致させようとしていますが、正しく実行できません。私が扱う必要のある文字列は次のようになります(例)

XY_efgh_1234_0040_rev_2_1_NC_asdf
XY_abcd_1122Ae_1150_rev2_1_NC
XY_efgh_0124e_50_NC
asdf_1980_2234a_2
XY_abcd_5098_2270_2_1_NC
PC_bos_7659Ae_1450sp_rev_2_1_NC_GRAPH

そこにあるパターンは一定ではなく、ある時点で変化する可能性があります。これは私にとって重要です:

  • 最初の数値まで、文字列の先頭を忘れてください。それは重要ではありません、私はこれを必要としません、それはどんな結果からも取り除かれるべきです。

  • その場合、常に4桁の数字があり、その後にアルファベット文字(最大3桁)を続けることができます。この部分が必要です、抽出しました。

  • 次に、アンダースコア(マイナスもある場合があります)の後に、必要な数値の別のセットがあります。これは常に2〜4です(...その後に最大3つのアルファベット文字が続く場合もあります)

  • このセクションの直後に、さらに下線で区切って、重要で前の値に属するさらに数値が存在する可能性があります。アルファベット文字も含まれている可能性があります...

  • 文字列の末尾には「NC」などの文字が含まれている可能性がありますが、重要ではないため、削除する必要があります。

したがって、前の例によれば、これは私が作業する必要があるものです:

('1234',   '0040_rev_2_1')
('1122Ae', '1150_rev2_1')
('0124e',  '50')
('1980',   '2234a_2')
('5098',   '2270_2_1')
('7659Ae', '1450sp_rev_2_1')

...私はRegExでそのようなことをしたことがありません、それは私を夢中にさせていますこれが私がこれまでに得たものですが、それは私が必要としているものではありません。

pattern     = re.compile(
              r"""
              ([0-9]{4}
              [A-Z]{0,3})
              [_-]{1,3}
              ([0-9]{2,4}
              [0-9A-Z_-]{0,16})
              """,
              re.IGNORECASE | 
              re.VERBOSE
              )

if re.search(pattern, string):
    print re.findall(pattern, string)

最後に述べた例でこれを使用すると、次のようになります。

[(u'7659Ae', u'1450sp_rev_2_1_NC_GR')]

...ほぼ必要なものですが、最後にこれを除外する方法がわかりません_NC_GR。また、文字数を制限するこの単純な方法は、適切ではありません。

誰かがこのケースにうまく機能する解決策を持っていますか?

4

2 に答える 2

3

が続かない文字に一致させるには、否定先読みを使用する必要がありますNC。グループ化を示すために、正規表現を少し再フォーマットします。

pattern     = re.compile(r"""
              ( [0-9]{4} [A-Z]{0,3} )
              [_-]{1,3}
              ( [0-9]{2,4} (?:[0-9A-Z_-](?!NC))* )
              """, re.IGNORECASE | re.VERBOSE)

を太字の量指定子に{0,16}置き換えると、次のようになります。*

>>> for match in pattern.findall(inputtext):
...     print match
... 
('1234', '0040_rev_2_1')
('1122Ae', '1150_rev2_1')
('0124e', '50')
('1980', '2234a_2')
('5098', '2270_2_1')
('7659Ae', '1450sp_rev_2_1')

そのため、(非キャプチャ) グループ(?:[0-9A-Z_-](?!NC))は、文字が続かない任意の数字、文字、アンダースコア、またはダッシュに一致しますNC

于 2013-03-19T19:17:37.020 に答える
2

私にとって、Martijnの解決策はうまくいきません。だから私は私の解決策を与えます。

私が使用していないという事実に注意してくださいre.IGNORECASE
したがって、私の正規表現は
PC_bos_7659Ae_1450sp_rev_2_1_nc_woof
I don't know if it is really what you want in this caseの最後をキャッチできます

inputtext = """XY_efgh_1234_0040_rev_2_1_NC_asdf
XY_abcd_1122Ae_1150_rev2_1_NC
XY_efgh_0124e_50_NC
asdf_1980_2234a_2
XY_abcd_5098_2270_2_1_NC
PC_bos_7659Ae_1450sp_rev_2_1_NC_GRAPH
PC_bos_7659Ae_1450sp_rev_2_1_nc_woof"""
print inputtext

.

import re

print """\n----------------------------------------
WANTED
('1234',   '0040_rev_2_1')
('1122Ae', '1150_rev2_1')
('0124e',  '50')
('1980',   '2234a_2')
('5098',   '2270_2_1')
('7659Ae', '1450sp_rev_2_1')"""
print '----------- eyquem ----------------------'
ri = re.compile('^\D+'
                '(\d{4}[a-zA-Z]{0,3})'
                '[_-]+'
                '(.+?)'
                '(?:[_-]+NC.*)?$',
                re.MULTILINE)

for match in ri.findall(inputtext):
    print match
    
print '----------- Martijn ----------------------'
ro     = re.compile(
              r"""
              ([0-9]{4}
              [A-Z]{0,3})
              [_-]{1,3}
              ([0-9]{2,4}
              [0-9A-Z_-]{0,16}?)
              (?:[-_]NC)?
              """,
              re.IGNORECASE | re.VERBOSE)

for match in ro.findall(inputtext):
    print match

結果

----------------------------------------
WANTED
('1234',   '0040_rev_2_1')
('1122Ae', '1150_rev2_1')
('0124e',  '50')
('1980',   '2234a_2')
('5098',   '2270_2_1')
('7659Ae', '1450sp_rev_2_1')
----------- eyquem ----------------------
('1234', '0040_rev_2_1')
('1122Ae', '1150_rev2_1')
('0124e', '50')
('1980', '2234a_2')
('5098', '2270_2_1')
('7659Ae', '1450sp_rev_2_1')
('7659Ae', '1450sp_rev_2_1_nc_woof')
----------- Martijn ----------------------
('1234', '0040')
('1122Ae', '1150')
('0124e', '50')
('1980', '2234')
('5098', '2270')
('7659Ae', '1450')
('7659Ae', '1450')

私の正規表現は個々の行で使用できます::

for s in inputtext.splitlines(True):
    print ri.match(s).groups()

同じ結果

.

編集

import re

inputtext = """XY_efgh_1234_0040_rev_2_1_NC_asdf
XY_abcd_1122Ae_1150_rev2_1_NC
XY_efgh_0124e_50_NC
XY_efgh_0228e_66-__NC
asdf_1980_2234a_2   
asdf_2999_133a
XY_abcd_5098_2270_2_1_NC
XY_abcd_6099_33370_2_1_NC
XY_abcd_6099_3370abcd_2_1_NC
PC_bos_7659Ae_1450sp_rev_2_1_NC_GRAPH
PC_bos_7659Ae_1450sp_rev_2_1___NC_GRAPH
PC_bos_7659Ae_1450sp_rev_2_1_nc_woof_NC
PC_bos_7659Ae_1450sp_rev_2_1_anc_woof_NC
PC_bos_7659Ae_1450sp_rev_2_1_abNC_woof_NC"""

print '----------- Martijn 2 ------------'
ruu     = re.compile(r"""
              ( [0-9]{4} [A-Z]{0,3} )
              [_-]{1,3}
              ( [0-9]{2,4} (?:[0-9A-Z_-](?!NC))* )
              """, re.IGNORECASE | re.VERBOSE)
for match in ruu.findall(inputtext):
    print match
print '----------- eyquem 2 ------------'
rii = re.compile('[_-]'
                '(\d{4}[A-Z]{0,3})'
                '[_-]{1,3}'
                '('
                  '(?=\d{2,4}[A-Z]{0,3}(?![\dA-Z]))'
                  '(?:[0-9A-Z_-]+?)'
                 ')'
                '(?:[-_]+NC.*)?'
                '(?![0-9A-Z_-])',
                re.IGNORECASE)
for m in rii.findall(inputtext):
    print m

結果

----------- Martijn 2 ------------
('1234', '0040_rev_2_1')
('1122Ae', '1150_rev2_1')
('0124e', '50')
('0228e', '66-_')
('1980', '2234a_2')
('2999', '133a')
('5098', '2270_2_1')
('6099', '33370_2_1')
('6099', '3370abcd_2_1')
('7659Ae', '1450sp_rev_2_1')
('7659Ae', '1450sp_rev_2_1__')
('7659Ae', '1450sp_rev_2_1')
('7659Ae', '1450sp_rev_2_1_')
('7659Ae', '1450sp_rev_2_1_a')
----------- eyquem 2 ------------
('1234', '0040_rev_2_1')
('1122Ae', '1150_rev2_1')
('0124e', '50')
('0228e', '66')
('1980', '2234a_2')
('2999', '133a')
('5098', '2270_2_1')
('7659Ae', '1450sp_rev_2_1')
('7659Ae', '1450sp_rev_2_1')
('7659Ae', '1450sp_rev_2_1')
('7659Ae', '1450sp_rev_2_1_anc_woof')
('7659Ae', '1450sp_rev_2_1_abNC_woof')

備考:

  • 私の正規表現は「33370_2_1」も「3370abcd_2_1」もキャッチしません。これは、「2〜4文字の後に最大3桁が続く可能性がある」というパターンを尊重しないためです。Martijn
    のソリューションはそれらをキャッチします

  • 私の正規表現によってキャッチされた部分の端はきれいです。Martijn のコードではそうではありません

  • Martijn の正規表現は、すべてのシーケンス NC または nc の前で停止します。アンダースコアが前になくても、つまり、これらのシーケンスが必要な部分の一部である文字であってもです。
    私の正規表現のこの特性が望ましくない場合は、私に言ってください、私はそれを変更します

于 2013-03-19T21:10:41.767 に答える