Почему это регулярное выражение Python возвращает неправильную строку - PullRequest
0 голосов
/ 22 апреля 2011

Ниже у меня есть фрагмент кода, который должен заменить одну строку другой, но, похоже, не делает этого. Я не питон или эксперт по регулярным выражениям, может кто-нибудь сказать мне, почему это может пойти не так.

def ReplaceCRC( file_path ):
    file = open(file_path,'r+');
    file_str = file.read()
    if( file_str <> '' ):
         crc_list        = re.findall(r'_CalcCRC[(]\s*"\w+"\s*[)]', file_str);
         strs_to_crc     = []
         new_crc_list    = []
         if( crc_list ):
              for crc in crc_list:
                   quote_to_crc    = re.search(r'"\w+"', crc);
                   str_to_crc      = re.search(r'\w+', quote_to_crc.group() ).group();
                   final           = hex(CalcCRC( str_to_crc ))[:2]
                   value           = '%08X' % CalcCRC( str_to_crc )
                   final           = final + value.upper()
                   final_crc       = Insert( crc, ', ' + final + ' ', -1)
                   new_crc_list.append( final_crc )
              if( new_crc_list <> [] ):
                   for i in range(len(crc_list)):
                       print crc_list[i]
                       print new_crc_list[i]
                       term = re.compile( crc_list[i] );
                       print term.sub( new_crc_list[i], file_str );

Это файл, над которым он работает:

printf( "0x%08X\n", _CalcCRC("THIS_IS_A_CRC") );
printf( "0x%08X\n", _CalcCRC("PATIENT_ZERO") );

Это вывод

_CalcCRC("THIS_IS_A_CRC")
_CalcCRC("THIS_IS_A_CRC", 0x97DFEAC9 )
printf( "0x%08X\n", _CalcCRC("THIS_IS_A_CRC") );
printf( "0x%08X\n", _CalcCRC("PATIENT_ZERO") );

_CalcCRC("PATIENT_ZERO")
_CalcCRC("PATIENT_ZERO", 0x0D691C21 )
printf( "0x%08X\n", _CalcCRC("THIS_IS_A_CRC") );
printf( "0x%08X\n", _CalcCRC("PATIENT_ZERO") );

Что нужно сделать, это найти строку CRC, вычислить значение и затем поместить строку на место в исходной строке. Я пробовал кучу вещей, но ничего не получается.

Ответы [ 3 ]

1 голос
/ 22 апреля 2011

Не ваша проблема, но эти 3 строки удивительны:

final           = hex(CalcCRC( str_to_crc ))[:2]
value           = '%08X' % CalcCRC( str_to_crc )
final           = final + value.upper()

Если предположить, что CalcCRC возвращает неотрицательное целое число (например, 12345567890

Строка 1 устанавливает final в "0x")независимо от ввода!

>>> hex(1234567890)
'0x499602d2'
>>> hex(1234567890)[:2]
'0x'

Строка 2 повторяет вызов CalcCRC!

>>> value           = '%08X' % 1234567890
>>> value
'499602D2'

Обратите внимание, что value - это уже прописные буквы!

и после строки 3 final становится '0x499602D2'

Поскольку value больше не используется, все это можно заменить на

final = '0x%08X' % CalcCRC(str_to_crc)

Еще отCircumlocution City

Эти строки:

quote_to_crc    = re.search(r'"\w+"', crc);
str_to_crc      = re.search(r'\w+', quote_to_crc.group() ).group();

можно заменить одним из:

str_to_crc = re.search (r '"\ w +"',crc) .group () [1: -1] str_to_crc = re.search (r '"(\ w +)"', crc) .group (1)

0 голосов
/ 22 апреля 2011

Ты этого хочешь?:

import re

def ripl(mat):
    return '%s, 0x%08X' % (mat.group(1),CalcCRC(mat.group(2)))

regx = re.compile(r'(_CalcCRC[(]\s*"(\w+)"\s*[)])')


def ReplaceCRC( file_path, regx = regx, ripl = ripl ):
    with open(file_path,'r+') as f:
        file_str = f.read()
        print file_str,'\n'
        if file_str:
             file_str = regx.sub(ripl,file_str)
             print file_str
             f.seek(0,0)
             f.write(file_str) 
             f.truncate()

РЕДАКТИРОВАТЬ

Я забыл инструкцию f.truncate(), очень важно, в противном случае она остается хвостом, если переписанное содержимое короче исходного содержимого

.

РЕДАКТИРОВАТЬ 2

Джон Мачин,

Нет ошибки, мое решение верное, оно дает

printf( "0x%08X\n", _CalcCRC("THIS_IS_A_CRC"), 0x97DFEAC9 ); 
printf( "0x%08X\n", _CalcCRC("PATIENT_ZERO"), 0x0D691C21 );

Я не имелизменил его с вашего комментария.Я думаю, что сначала я опубликовал решение, которое было неправильным (потому что я выполнил несколько различных тестов, чтобы проверить некоторые поведения и, вы знаете, я иногда смешиваю свои файлы и коды), затем вы скопировали этот неправильный код, чтобы попробовать его,Затем я понял, что произошла ошибка, и исправил код, а затем вы опубликовали свой комментарий, не заметив, что я исправил.Я не представляю другой причины такой путаницы.

Кстати, для получения того же результата в шаблоне даже нет необходимости в двух группах, определяющих regx , одной достаточно.Следующие regx и ripl() также работают:

regx = re.compile(r'_CalcCRC\(\s*"(\w+)"\s*\)')
# I prefer '\(' to '[(]', and same for '\)' instead of '[)]'

def ripl(mat):
    return '%s, 0x%08X' % (mat.group(),CalcCRC(mat.group(1)))

Но остается неопределенность.Каждый наш результат мудр, относительно неточной формулировки Джо.Итак, чего он хочет в качестве точного результата?: должно ли значение 0x97DFEAC9 быть вставлено в CalcCRC("THIS_IS_A_CRC"), как в вашем результате, или после CalcCRC("THIS_IS_A_CRC"), как в моем?

Чтобы сказать все, я хотел, чтобы вы получили код, которыйможно запустить: я определил собственную функцию CalcCRC () , состоящую просто из if x=="THIS_IS_A_CRC": return 0x97DFEAC9 и if x=="PATIENT_ZERO": return 0x0D691C21;Я обнаружил эти ассоциации, увидев результаты, которые Джо желал раскрыть в своем вопросе.

Теперь, касаясь вашего противного утверждения, что мой «пункт о переопределении функций - полная чушь» , я думаюЯ недостаточно объяснил, что я имею в виду.Размещение регулярного выражения regx и функции ripl () в качестве аргументов по умолчанию для параметров функции ReplaceCRC () имеет следствие: объекты regx и ripl () создаются только один раз, в настоящий момент выполняется определение функции ReplaceCRC () .Таким образом, в случае, если ReplaceCRC () будет применен несколько раз при выполнении, повторное создание этих объектов не будет.Я не знаю, действительно ли функция ReplaceCRC () вызывается несколько раз во время выполнения программы Джо, но я считаю хорошей практикой использовать эту функцию в коде на случай, если она может быть полезной.Возможно, я должен был подчеркнуть этот момент в своем ответе вместо комментария, чтобы оправдать мой код относительно вашего.Но я стараюсь ограничивать свою склонность писать иногда слишком длинные ответы.

Проясняются ли эти моменты, и ваше раздражение смягчается этими объяснениями?

0 голосов
/ 22 апреля 2011

Быстрый взгляд на реальный ответ:

Вам необходимо (среди прочего) использовать re.escape () ....

term = re.compile(re.escape(crc_list[i]))

и отступ на вашем последнем if выглядит набитым.

... еще после обеда: -)

Постпрандиальное обновление

Вы делаете 3 прохода по всему файлу, когда только один сделает трюк. Помимо сокращения огромного количества беспорядка, основным нововведением является использование функции re.sub, которая позволяет замене быть функцией вместо строки.

import re
import zlib

def CalcCRC(s):
    # This is an example. It doesn't produce the same CRC as your examples do.
    return zlib.crc32(s) & 0xffffffff

def repl_func(mobj):
    str_to_crc = mobj.group(2)
    print "str_to_crc:", repr(str_to_crc)
    crc = CalcCRC(str_to_crc)
    # If my guess about Insert(s1, s2, n) was wrong,
    # adjust the ollowing statement.
    return '%s"%s", 0x%08X%s' % (mobj.group(1), mobj.group(2), crc, mobj.group(3))

def ReplaceCRC(file_handle):
    regex = re.compile(r'(_CalcCRC[(]\s*)"(\w+)"(\s*[)])')
    for line in file_handle:
        print "line:", repr(line)
        line2 = regex.sub(repl_func, line)
        print "line2:", repr(line2)
    return

if __name__ == "__main__":
    import sys, cStringIO
    args = sys.argv[1:]
    if args:
        f = open(args[0], 'r')
    else:
        f = cStringIO.StringIO(r"""
printf( "0x%08X\n", _CalcCRC("THIS_IS_A_CRC") )
other_stuff()
printf( "0x%08X\n", _CalcCRC("PATIENT_ZERO") )
""")
    ReplaceCRC(f)

Результат выполнения сценария без аргументов:

line: '\n'
line2: '\n'
line: 'printf( "0x%08X\\n", _CalcCRC("THIS_IS_A_CRC") )\n'
str_to_crc: 'THIS_IS_A_CRC'
line2: 'printf( "0x%08X\\n", _CalcCRC("THIS_IS_A_CRC", 0x98ABAC4B) )\n'
line: 'other_stuff()\n'
line2: 'other_stuff()\n'
line: 'printf( "0x%08X\\n", _CalcCRC("PATIENT_ZERO") )\n'
str_to_crc: 'PATIENT_ZERO'
line2: 'printf( "0x%08X\\n", _CalcCRC("PATIENT_ZERO", 0x76BCDA4E) )\n'
...