如何反转正则表达式替换?

时间:2013-03-03 17:35:38

标签: python regex

回到这个例子,

Having trouble dealing with similar characters to print different things using regex in Python

我想知道如何改变我所做的正则表达式替换并打印出原始文本?

就是这样,如果我有

text = "This is my first regex python example yahooa yahoouuee bbbiirdd"

作为我的原始文本,然后它的输出将是:

re.sub text = "tookhookisook isook mookyook fookirooksooktook pookyooktookhookonook..."

然后我希望将输出转换回原始文本。

我该怎么做?

3 个答案:

答案 0 :(得分:4)

Python字符串是不可变的。您还没有更改原始文件,只创建了一个新字符串。只需保留对原文的引用。

修改
通过不可变,我的意思是它们的实际值在创建后被冻结。

>>> s = "abc"
>>> s[0]
'a'
>>> s[1] = 'd'

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    s[1] = 'd'
TypeError: 'str' object does not support item assignment
>>> 

在上面的例子中,我可以让变量s引用另一个对象,但我赋给它的字符串是常量。因此,当您执行s.replace()时,结果是 new 字符串,并且原始字符串保持不变。

>>> s.replace ('a', 'd')
'dbc'
>>> s
'abc'
>>> 

答案 1 :(得分:1)

这似乎有效:

import re 

tu = ('This is my first regex python example '
      'yahooa yahoouuee bbbiirdd',

      'bbbiirdd',

      'fookirooksooktook',

      'crrsciencezxxxxxscienceokjjsciencq')

reg   = re.compile(r'([bcdfghj-np-tv-z])(\1?)')
dereg = re.compile('science([^aeiou])|([^aeiou])ook')

def Frepl(ma):
    g1,g2 = ma.groups()
    if g2:  return 'science' + g2
    else:   return g1 + 'ook'

def Fderepl(ma):
    g = ma.group(2)
    if g:  return g
    else:  return 2*ma.group(1)

for strt in tu:
    resu =   reg.sub(Frepl  , strt)
    bakk = dereg.sub(Fderepl, resu)
    print ('----------------------------------\n'
           'strt = %s\n'    'resu == %s\n'
           'bakk == %s\n'   'bakk == start : %s'
           % (strt, resu, bakk, bakk==strt))

修改

首先,我更新了上面的代码:我删除了re.I标志。它正在捕捉像'dD'这样的重复字母。所以它被转换为'scienceD',然后回到'DD'

其次,我用字典扩展了代码 它不是用字母+'ook'替换字母,而是根据字母替换 例如,我选择用'BAR'替换'b',用'CORE'替换'c'....我把字典的值大写,以便更好地查看结果。实际上它可能是其他任何东西 程序负责处理此案。我在字典中只放了'T','Y','X',这只是为了文章。

import re 

d = {'b':'BAR','c':'CORE','d':'DEAD','f':'FAN',
     'g':'GO','h':'HHH','j':'JIU','k':'KOAN',
     'l':'LOW','m':'MY','n':'NERD','p':'PI',
     'q':'QIM','r':'ROAR','s':'SING','t':'TIP',
     'v':'VIEW','w':'WAVE','x':'XOR',
     'y':'YEAR','z':'ZOO',
     'T':'tears','Y':'yearling','X':'xylophone'}

ded = dict((v,k) for k,v in d.iteritems())
print ded

tu = ('This is my first regex python example '
       'Yahooa yahoouuee bbbiirdd',

      'bbbiirdd',

      'fookirooksooktook',

      'crrsciencezxxxxxXscienceokjjsciencq')

reg   = re.compile(r'([bcdfghj-np-tv-zBCDFGHJ-NP-TV-Z])(\1?)')

othergr = '|'.join(ded.keys())
dereg = re.compile('science([^aeiouAEIOU])|(%s)' % othergr)

def Frepl(ma, d=d):
    g1,g2 = ma.groups()
    if g2:  return 'science' + g2
    else:   return d[g1]

def Fderepl(ma,ded=ded):
    g = ma.group(2)
    if g:  return ded[g]
    else:  return 2*ma.group(1)

for strt in tu:
    resu =   reg.sub(Frepl  , strt)
    bakk = dereg.sub(Fderepl, resu)
    print ('----------------------------------\n'
           'strt = %s\n'    'resu == %s\n'
           'bakk == %s\n'   'bakk == start : %s'
           % (strt, resu, bakk, bakk==strt))

结果

----------------------------------
strt = This is my first regex python example Yahooa yahoouuee bbbiirdd
resu == tearsHHHiSING iSING MYYEAR FANiROARSINGTIP ROAReGOeXOR PIYEARTIPHHHoNERD eXORaMYPILOWe yearlingaHHHooa YEARaHHHoouuee sciencebBARiiROARscienced
bakk == This is my first regex python example Yahooa yahoouuee bbbiirdd
bakk == start : True
----------------------------------
strt = bbbiirdd
resu == sciencebBARiiROARscienced
bakk == bbbiirdd
bakk == start : True
----------------------------------
strt = fookirooksooktook
resu == FANooKOANiROARooKOANSINGooKOANTIPooKOAN
bakk == fookirooksooktook
bakk == start : True
----------------------------------
strt = crrsciencezxxxxxXscienceokjjsciencq
resu == COREsciencerSINGCOREieNERDCOREeZOOsciencexsciencexXORxylophoneSINGCOREieNERDCOREeoKOANsciencejSINGCOREieNERDCOREQIM
bakk == crrsciencezxxxxxXscienceokjjsciencq
bakk == start : True

答案 2 :(得分:0)

您无法在Python或任何其他正则表达式实现中向后“转换”正则表达式替换。

这只是因为替换是一条返回新字符串的单行道,并且没有神奇的反转功能

以下是使用string.replace():

的插图
original_string = 'abc'
newstring = original_string.replace('a','b')
'bbc'

将newstring转换为'abc'不仅仅是将'b'替换为'a'。你不能在任何给定的正则表达式中创建一个“反向”正则表达式。如果我们在这个例子中用'a'替换'b',那么字符串将是'aac' - 而不是bbc。

正则表达式函数的工作原理与string.replace相同 - 它们返回一个新字符串。它们不会返回一个知道每个正则表达式替换的确切状态的对象。

你有两个选择可以做你想做的事情:

1-创建一个表示字符串并跟踪(无限?)个正则表达式操作的自定义类,允许您在每个状态之间创建差异。

2-做其他人做的事情,这里有很多人建议:你只需将原始字符串(或其副本)存放到一边。

(这是为了简化@StoryTeller的答案)