2013-06-17 2 views
1

Мне нужно совместить объекты с именем согласно спецификации файла PDF. Однако имена могут содержать шестнадцатеричные цифры (предшествующие #) для указания специальных символов. Я хотел бы перевести эти совпадения на соответствующие символы. Есть ли разумный способ сделать это без повторного разбора строки соответствия?Перевод регулярных выражений групп

import re 

Name = re.compile(r''' 
    (/          # Literal "/" 
     (?:         # 
      (?:\#[A-Fa-f0-9]{2})    # Hex numbers 
      |         # 
      [^\x00-\x20 \x23 \x2f \x7e-\xff] # Other 
     )+         # 
    )           # 
    ''', re.VERBOSE) 

# some examples 

names = """ 
    The following are examples of valid literal names: 

    Raw string      Translation 

    1. /Adobe#20Green   -> "Adobe Green" 
    2. /PANTONE#205757#20CV  -> "PANTONE 5757 CV" 
    3. /paired#28#29parentheses -> "paired()parentheses" 
    4. /The_Key_of_F#23_Minor -> "The_Key_of_F#_Minor" 
    5. /A#42      -> "AB" 
    6. /Name1 
    7. /ASomewhatLongerName 
    8. /A;Name_With-Various***Characters? 
    9. /1.2 
    10. /$$ 
    11. /@pattern 
    12. /.notdef 
    """ 
+0

Вы хотите заменить это на входной строке? Или вы хотите перечислить совпадающие имена с неубедительными escape-последовательностями? –

+0

Можете ли вы использовать 're.sub'? –

+0

@MartijnPieters - 'список совпадающих имен с escape-последовательностями unescaped' – root

ответ

1

Я хотел бы использовать finditer() с оберточной генератора:

import re 
from functools import partial 

def _hexrepl(match): 
    return chr(int(match.group(1), 16)) 
unescape = partial(re.compile(r'#([0-9A-F]{2})').sub, _hexrepl) 

def pdfnames(inputtext): 
    for match in Name.finditer(inputtext): 
     yield unescape(match.group(0)) 

Демо:

>>> for name in pdfnames(names): 
...  print name 
... 
/Adobe Green 
/PANTONE 5757 CV 
/paired()parentheses 
/The_Key_of_F#_Minor 
/AB 
/Name1 
/ASomewhatLongerName 
/A;Name_With-Various***Characters? 
/1.2 
/$$ 
/@pattern 
/.notdef 

Существует не более умный способ что I Знание; двигатель re не может комбинировать замену и сопоставление.

+0

Спасибо, тогда 're.sub' это :) – root

1

Посмотрите на re.sub.

Вы можете использовать это с функцией для соответствия шестизначным номерам # [0-9A-F] {2} 'и перевести их с помощью функции.

E.g.

def hexrepl(m): 
    return chr(int(m.group(0)[1:3],16)) 

re.sub(r'#[0-9A-F]{2}', hexrepl, '/Adobe#20Green') 

Вернется '/ Adobe Green'

+0

Я довольно чертовски уверена, что @root знает о 're.sub'. –

+0

@MartijnPieters Тогда ему также должно быть остроумие упомянуть, что в вопросе и почему это не работает :) –

+0

@Jack: Я прошу разъяснений; то, что он хочет, не ясно. –