Python, извлечение чисел из столбца Excel и запись в виде вывода

1

Попытка извлечь номер из столбцов в файле Excel и записать их в следующие столбцы.

Критерии соответствия: любое число из пяти, либо начато с "PB", либо нет

Ive ограничил длину совпадения числа до пяти, но есть "16" извлеченных (строка №2, столбец D)

Изображение 174551

Как я могу это улучшить? Спасибо.

import xlwt, xlrd, re
from xlutils.copy import copy 

workbook = xlrd.open_workbook("C:\\Documents\\num.xlsx")
old_sheet = workbook.sheet_by_name("Sheet1")

wb = copy(workbook) 
sheet = wb.get_sheet(0)

number_of_ships = old_sheet.nrows

for row_index in range(0, old_sheet.nrows):

    Column_a = old_sheet.cell(row_index, 0).value   
    Column_b = old_sheet.cell(row_index, 1).value

    a_b = Column_a + Column_b

    found_PB = re.findall(r"[PB]+(\d{5})", a_b, re.I)
    list_of_numbers = re.findall(r'\d+', a_b)

    for f in found_PB:
        if len(f) == 5:
            sheet.write(row_index, 2, "";"".join(found_PB))

    for l in list_of_numbers:
        if len(l) == 5:
            sheet.write(row_index, 3, "";"".join(list_of_numbers))

wb.save("C:\\Documents\\num-1.xls")    
  • 1
    Если вы используете \d+ , он будет просто извлекать куски из 1 + цифр, поэтому вы ничего не ограничивали. Если вам нужны цифры после PB , напишите PB , а не [PB] (класс символов, соответствующий либо P либо B ).
  • 0
    @WiktorStribiżew WiktorStribiżew, спасибо! не могли бы вы поставить это как ответ, чтобы я мог закрыть его? Или лучше удалить этот вопрос?
Показать ещё 5 комментариев
Теги:
excel

2 ответа

3
Лучший ответ

Ваш шаблон \d+ соответствует любым 1 или более цифрам, поэтому значение 16 соответствует. Ваш класс символа [PB]+ совпадает с P или B один или несколько раз, поэтому он ограничивает цифры, которым предшествуют либо P либо B Поскольку вы хотите сопоставить любые цифры, вам фактически не нужно это ограничение (если A может предшествовать чему-то дополнительно, ограничение больше не имеет смысла).

Вам также, кажется, нужно извлечь 5-значную строку точно, когда никакие другие цифры не предшествуют или не следуют за ними. Вы можете сделать это с помощью (?<!\d)\d{5}(?!\d). Отрицательный lookbehind (?<!\d) гарантирует, что в левой части текущего местоположения нет цифры, \d{5} потребляет 5 цифр, а отрицательный результат (?!\d) гарантирует, что нет цифры сразу справа от текущего местоположения. Это делает избыточную строку if len(l) == 5: и вы можете опустить всю часть кода, связанную с list_of_numbers.

Таким образом, вы можете просто использовать

import xlwt, xlrd, re
from xlutils.copy import copy 

workbook = xlrd.open_workbook("C:\\Documents\\num.xlsx")
old_sheet = workbook.sheet_by_name("Sheet1")

wb = copy(workbook) 
sheet = wb.get_sheet(0)

number_of_ships = old_sheet.nrows

for row_index in range(0, old_sheet.nrows):

    Column_a = old_sheet.cell(row_index, 0).value   
    Column_b = old_sheet.cell(row_index, 1).value

    a_b = Column_a + Column_b

    found_PB = re.findall(r"(?<!\d)\d{5}(?!\d)", a_b)

    for f in found_PB:
            sheet.write(row_index, 2, "";"".join(found_PB))

wb.save("C:\\Documents\\num-1.xls")    
  • 1
    благодарю вас! люблю этот "негативный взгляд"!
  • 0
    но если ячейка содержит более 1 5 цифр, как поймать их все? (например, ячейка A2 - это «PB65352, 456789»)
Показать ещё 2 комментария
1

Вы можете использовать это: ^(?:PB)?\d{5}$

демонстрация

Разъяснение:

^           # Begin of line/string
  (?:       # Begin of group
     PB     #   Literal 'PB'
  )         # End of group
  ?         # Make the previous group optional (? means 0 or 1 times)
  \d{5}     # 5 digits
$           # End of line/string

Важно использовать $, так как если бы вы только что написали ^(?:PB)?\d{5} вы бы соответствовали 6-значным числам, даже если вы написали \d{5} это потому, что вы бы соответствовали первым пятизначным числам и вы остановитесь там, не зная, есть ли больше цифр.

Если ваши данные могут начинаться или заканчиваться пробелами, вы можете использовать это вместо: ^\s*(?:PB)?\d{5}\s*$ В основном это добавляет \s* в начале и в конце регулярного выражения. \s* означает 0 или более пробелов.

  • 0
    спасибо за обмен и помощь. Вы не возражаете, я выберу Wiktor Stribiżew для его получения большего числа голосов? Я тоже могу отдать тебе голос. :)
  • 1
    Просто примите то, что работает лучше для вас, и upvote, если это полезно для вас :) @MarkK
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню