Попытка извлечь номер из столбцов в файле Excel и записать их в следующие столбцы.
Критерии соответствия: любое число из пяти, либо начато с "PB", либо нет
Ive ограничил длину совпадения числа до пяти, но есть "16" извлеченных (строка №2, столбец D)
Как я могу это улучшить? Спасибо.
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")
Ваш шаблон \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")
Вы можете использовать это: ^(?: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 или более пробелов.
\d+
, он будет просто извлекать куски из 1 + цифр, поэтому вы ничего не ограничивали. Если вам нужны цифры послеPB
, напишитеPB
, а не[PB]
(класс символов, соответствующий либоP
либоB
).