2

以下のケースでは、文字列「Singapore」に一致させたいと考えています。ここで、「S」は常に大文字で、残りの単語は小文字でも大文字でもかまいません。ただし、以下の文字列「s」は小文字で、検索条件に一致します。これを実装する方法を教えてもらえますか?

       import re       
            st = "Information in sinGapore "

            if re.search("S""(?i)(ingapore)" , st):
                print "matched"

Singapore => matched  
sIngapore => notmatched  
SinGapore => matched  
SINGAPORE => matched
4

5 に答える 5

5

コメントしたように、醜い方法は次のようになります。

>>> re.search("S[iI][Nn][Gg][Aa][Pp][Oo][Rr][Ee]" , "SingaPore")
<_sre.SRE_Match object at 0x10cea84a8>
>>> re.search("S[iI][Nn][Gg][Aa][Pp][Oo][Rr][Ee]" , "Information in sinGapore")

よりエレガントな方法は、大文字と小文字を区別せずにシンガポールを照合し、最初の文字が であることを確認することですS

reg=re.compile("singapore", re.I)

>>> s="Information in sinGapore"
>>> reg.search(s) and reg.search(s).group()[0]=='S'
False

>>> s="Information in SinGapore"
>>> reg.search(s) and reg.search(s).group()[0]=='S'
True

アップデート

あなたのコメントに続いて - あなたは使用することができます:

reg.search(s).group().startswith("S")

それ以外の:

reg.search(s).group()[0]==("S")

もっと読みやすいと思われる場合。

于 2013-02-25T16:23:38.127 に答える
2

単純なラムダを記述して、醜いがすべての解決策を生成できます。

>>> leading_cap_re = lambda s: s[0].upper() + ''.join('[%s%s]' % 
                                                    (c.upper(),c.lower()) 
                                                        for c in s[1:])
>>> leading_cap_re("Singapore")
'S[Ii][Nn][Gg][Aa][Pp][Oo][Rr][Ee]'

複数単語の都市の場合、文字列分割バージョンを定義します。

>>> leading_caps_re = lambda s : r'\s+'.join(map(leading_cap_re,s.split()))
>>> print leading_caps_re('Kuala Lumpur')
K[Uu][Aa][Ll][Aa]\s+L[Uu][Mm][Pp][Uu][Rr]

次に、コードは次のようになります。

if re.search(leading_caps_re("Singapore") , st):
    ...etc...

REの醜さは純粋に内部的なものです。

于 2013-02-25T17:33:31.310 に答える
2

キャッチフレーズに従ってGVコードを設定したいので(一意の名前またはいくつかの名前の空白で区切られていることはわかっています)、キャッチフレーズに従って辞書でコードを選択するステップが必要です。
したがって、正規表現では不可能なフレーズの最初の文字 (大文字にする必要があります) または名に対してテストを実行するために、このステップを利用するのは簡単です。

テストを構成する特定の条件を選択しました。たとえば、名のドットは必須ではありませんが、大文字は必須です。これらの条件は、必要に応じて簡単に変更できます。

編集1

import re

def regexize(cntry):
    def doot(x):
        return '\.?'.join(ch for ch in x) + '\.?'
    to_join = []
    for c in cntry:
        cspl = c.split(' ',1)
        if len(cspl)==1: # 'Singapore','Austria',...
            to_join.append('(%s)%s'
                           % (doot(c[0]), doot(c[1:])))
        else: # 'Den LMM','LMM Den',....
            to_join.append('(%s) +%s'
                           % (doot(cspl[0]),
                              doot(cspl[1].strip(' ').lower())))
    pattern = '|'.join(to_join).join('()')
    return re.compile(pattern,re.I)

def code(X,CNTR,r = regexize):
    r = regexize(CNTR)
    for ma in r.finditer(X):
        beg = ma.group(1).split(' ')[0]
        if beg==ma.group(1):
            GV = countries[beg[0]+beg[1:].replace('.','').lower()] \
                 if beg[0].upper()==beg[0] else '- bad match -'
        else:
            try:
                k = (ki for ki in countries.iterkeys()
                     if beg.replace('.','')==ki.split(' ')[0]).next()
                GV = countries[k]
            except StopIteration:
                GV = '- bad match -'
        yield '  {!s:15}  {!s:^13}'.format(ma.group(1), GV)

countries = {'Singapore':'SG','Austria':'AU',
             'Swiss':'CH','Chile':'CL',
             'Den LMM':'DN','LMM Den':'LM'}

s = ('  Singapore  SIngapore  SiNgapore  SinGapore'
     '  SI.Ngapore  SIngaPore  SinGaporE  SinGAPore'
     '  SINGaporE  SiNg.aPoR   singapore  sIngapore'
     '  siNgapore  sinGapore  sINgap.ore  sIngaPore'
     '  sinGaporE  sinGAPore  sINGaporE  siNgaPoRe'
     '    Austria    Aus.trIA    aUSTria    AUSTRiA'
     '  Den L.M.M     Den   Lm.M    DEn Lm.M.'
     '  DEN L.MM      De.n L.M.M.     Den LmM'
     '    L.MM   DEn      LMM DeN     LM.m  Den')

print '\n'
print '\n'.join(res for res in code(s,countries))

編集2

コードを改善しました。より短く、読みやすくなっています。
指示assert(.....]は、辞書のキーが目的に対して適切に形成されていることを確認することです。

import re

def doot(x):
    return '\.?'.join(ch for ch in x) + '\.?'

def regexize(labels,doot=doot,
             wg2 = '(%s) *( %s)',wnog2 = '(%s)(%s)',
             ri = re.compile('(.(?!.*? )|[^ ]+)( ?) *(.+\Z)')):
    to_join = []
    modlabs = {}
    for K in labels.iterkeys():
        g1,g2,g3 = ri.match(K).groups()
        to_join.append((wg2 if g2 else wnog2)
                       % (doot(g1), doot(g3.lower())))
        modlabs[g1+g2+g3.lower()] = labels[K]
    return (re.compile('|'.join(to_join), re.I), modlabs)



def code(X,labels,regexize = regexize):
    reglab,modlabs = regexize(labels)
    for ma in reglab.finditer(X):
        a,b = tuple(x for x in ma.groups() if x)
        k = (a + b.lower()).replace('.','')
        GV = modlabs[k] if k in modlabs else '- bad match -'
        yield '  {!s:15}  {!s:^13}'.format(a+b, GV)

countries = {'Singapore':'SG','Austria':'AU',
             'Swiss':'CH','Chile':'CL',
             'Den LMM':'DN','LMM Den':'LM'}

assert(all('.' not in k and
          (k.count(' ')==1 or k[0].upper()==k[0])
          for k in countries))

s = ('  Singapore  SIngapore  SiNgapore  SinGapore'
     '  SI.Ngapore  SIngaPore  SinGaporE  SinGAPore'
     '  SINGaporE  SiNg.aPoR   singapore  sIngapore'
     '  siNgapore  sinGapore  sINgap.ore  sIngaPore'
     '  sinGaporE  sinGAPore  sINGaporE  siNgaPoRe'
     '    Austria    Aus.trIA    aUSTria    AUSTRiA'
     '  Den L.M.M     Den   Lm.M    DEn Lm.M.'
     '  DEN L.MM      De.n L.M.M.     Den LmM'
     '    L.MM   DEn      LMM DeN     LM.m  Den')

print '\n'.join(res for res in code(s,countries))
于 2013-03-04T17:42:51.793 に答える
1

興味深いことに

/((S)((?i)ingapore))/

perl では正しいことを行いますが、python では必要に応じて機能しないようです。公平を期すために、python docs で明確に説明されていますが、 (?i) は正規表現全体を変更します

于 2013-02-25T17:33:53.283 に答える