2016-04-29 9 views
1

次再:中Pythonは即座にグループ名とグループを置き換える正規表現

import re 
s = "the blue dog and blue cat wore 7 blue hats 9 days ago" 
p = re.compile(r'blue (?P<animal>dog|cat)') 
p.sub(r'\1',s) 

結果、

'the dog and cat wore 7 blue hats 9 days ago' 

re.subを書き込むことができるように:

import re 
s = "the blue dog and blue cat wore 7 blue hats 9 days ago" 
p = re.compile(r'blue (?P<animal>dog|cat)|(?P<numberBelowSeven>[0-7])|(?P<numberNotSeven>[8-9])') 

は、

'the animal and animal wore numberBelowSeven blue hats numberNotSeven days ago" 

不思議十分replace strings豊富とgetting group namesではなく、両方を行うには十分に文書化途中のドキュメントがあります。

re.sub()複数回呼び出すことはありませんなぜ

答えて

0

>>> s = re.sub(r"blue (dog|cat)", "animal", s) 
>>> s = re.sub(r"\b[0-7]\b", "numberBelowSeven", s) 
>>> s = re.sub(r"\b[8-9]\b", "numberNotSeven", s) 
>>> s 
'the animal and animal wore numberBelowSeven blue hats numberNotSeven days ago' 

あなたはその後、「変更の一覧」にそれを入れて、一つ一つを適用することができます。私はしました

>>> changes = [ 
...  (re.compile(r"blue (dog|cat)"), "animal"), 
...  (re.compile(r"\b[0-7]\b"), "numberBelowSeven"), 
...  (re.compile(r"\b[8-9]\b"), "numberNotSeven") 
... ] 
>>> s = "the blue dog and blue cat wore 7 blue hats 9 days ago" 
>>> for pattern, replacement in changes: 
...  s = pattern.sub(replacement, s) 
... 
>>> s 
'the animal and animal wore numberBelowSeven blue hats numberNotSeven days ago' 

注意をさらに単語境界チェック(\b)が追加されました。

+0

私は40 + teをまとめて検索する20以上のグループでこれを行う必要があるためrandはパンダのデータフレームに200,000列の高さ – zelusp

+0

彼は "青い動物"が "動物"に変身したかった – lazary

+0

@lazary良いキャッチ、固定、ありがとう。 – alecxe

1

あなたはmatchobj.lastgroupを返しre.sub with a callback使用することができますあなたはパンダを使用している場合、あなたはSeries.str.replaceを使用することができることを注意

import re 

s = "the blue dog and blue cat wore 7 blue hats 9 days ago" 
p = re.compile(r'blue (?P<animal>dog|cat)|(?P<numberBelowSeven>[0-7])|(?P<numberNotSeven>[8-9])') 

def callback(matchobj): 
    return matchobj.lastgroup 

result = p.sub(callback, s) 
print(result) 

利回り

the animal and animal wore numberBelowSeven blue hats numberNotSeven days ago 

を:

import pandas as pd 

def callback(matchobj): 
    return matchobj.lastgroup 

df = pd.DataFrame({'foo':["the blue dog", "and blue cat wore 7 blue", "hats 9", 
          "days ago"]}) 
pat = r'blue (?P<animal>dog|cat)|(?P<numberBelowSeven>[0-7])|(?P<numberNotSeven>[8-9])' 
df['result'] = df['foo'].str.replace(pat, callback) 
print(df) 

利回り

     foo         result 
0    the blue dog        the animal 
1 and blue cat wore 7 blue and animal wore numberBelowSeven blue 
2     hats 9     hats numberNotSeven 
3     days ago        days ago 

という名前のグループを入れ子にしている場合、あなたはmatchobj.groupdict().items()を反復処理は、関連するすべてのグループ名を収集するために、より複雑なコールバックが必要な場合があります。

import pandas as pd 

def callback(matchobj): 
    names = [groupname for groupname, matchstr in matchobj.groupdict().items() 
      if matchstr is not None] 
    names = sorted(names, key=lambda name: matchobj.span(name)) 
    result = ' '.join(names) 
    return result 

df = pd.DataFrame({'foo':["the blue dog", "and blue cat wore 7 blue", "hats 9", 
          "days ago"]}) 

pat=r'blue (?P<animal>dog|cat)|(?P<numberItem>(?P<numberBelowSeven>[0-7])|(?P<numberNotSeven>[8-9]))' 

# pat=r'(?P<someItem>blue (?P<animal>dog|cat)|(?P<numberBelowSeven>[0-7])|(?P<numberNotSeven>[8-9]))' 

df['result'] = df['foo'].str.replace(pat, callback) 
print(df) 

利回りを

     foo           result 
0    the blue dog          the animal 
1 and blue cat wore 7 blue and animal wore numberItem numberBelowSeven blue 
2     hats 9     hats numberItem numberNotSeven 
3     days ago           days ago 
+0

これは私の質問にうまく答えます - ありがとう!私は予想外の問題に遭遇しました。テキストの一部を置き換えるために使用している名前のグループは、実際にはグループ内にあります。 ??猫)| |(P [0-7])?|?(P 'パット= R '(P 青(P 犬ならばどのようにして同じように動作するようにこれを修正します[8-9])) ''? – zelusp

+0

私たちが既に持っている例をうまく利用するには、あなたの解決策を拡張して* 'numberItem' *グループ内のグループ名を返すことができるかどうか*' pat = r'blue(? – zelusp

+1

私は対処できる代替のコールバックを追加しました。(これは、ネストされた名前付きグループ。 – unutbu

関連する問題