Форум программистов, компьютерный форум, киберфорум
Python для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9

Заменить номер года с помошью регулярного выражения

13.10.2023, 17:26. Показов 586. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.
Данный код должен перебрать все строки в файле и заменить указанные номера в переменной OldYears на года в переменной NewYears.
Например:
Code
1
сегодня 2022 год
Заменяется на:
Code
1
сегодня 2023 год
Code
1
сегодня 2024 год
Получаем два варианта замены, так как в переменной NewYears указанно два года.

Код ниже работает, когда год встречается в начале строки. Остальные два случая он не обрабатывает. Помогите разобраться.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# -*- coding: utf-8 -*-
 
from tqdm.auto import tqdm
import re
 
 
def ReplaceYears(
    InputFileKeys: str, 
    OutputFileKeys: str, 
    OldYears: set, 
    NewYears: set
):
    """
    заменяем нужные года на новые года, например, заменяем 2021 и 2022 года на 2023 и 2024
    """
 
    pattern1 = ''
    pattern2 = ''
    pattern3 = ''
    for old_year in OldYears:
        # год в начале строки
        pattern1 += f'(^{old_year}\s)|'
        # год в конце строки
        pattern2 += f'(\s{old_year}$)|'
        # год в середине строки
        pattern3 += f'(\s{old_year}\s)|'
    pattern1 = pattern1[:-1]
    pattern2 = pattern2[:-1]
    pattern3 = pattern3[:-1]
 
    pattern1 = re.compile(pattern1)
    pattern2 = re.compile(pattern2)
    pattern3 = re.compile(pattern3)
 
    KeyList = list()
    with open(InputFileKeys, 'r', encoding = 'utf-8') as file_input:
        for line in file_input.readlines():
            KeyList.append(line.strip())
 
    Res = set()
    for key in KeyList:
        for new_year in NewYears:
            new_key = key
            # если нашли соответствие
            if re.match(pattern1, new_key):
                new_key = re.sub(pattern1, f'{new_year} ', new_key)
            if re.match(pattern2, new_key):
                new_key = re.sub(pattern2, f' {new_year}', new_key)
            if re.match(pattern3, new_key):
                new_key = re.sub(pattern3, f' {new_year} ', new_key)
            Res.add(new_key)
            #print(key.strip(), '|', new_key.strip())
 
    with open(OutputFileKeys, 'w', encoding = 'utf-8') as text_file:
        for line in Res:
            text_file.write(f'{line.strip()}\n')
 
 
if __name__ == "__main__":
    OldYears = {2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022}
    NewYears = {2023, 2024}
 
    InputFileKeys = 'test.txt'
    OutputFileKeys = 'test_.txt'
    ReplaceYears(InputFileKeys, OutputFileKeys, OldYears, NewYears)
Добавлено через 2 минуты
Для примера:
Code
1
2
3
tretert ertet r2020 gdfgfg 2020
2021 fdsgdf sg dfg 2022
gddgds es dg 2022 dgd ggdsgd
Результат:
Code
1
2
3
4
5
6
tretert ertet r2020 gdfgfg 2023
tretert ertet r2020 gdfgfg 2024
2023 fdsgdf sg dfg 2023
2024 fdsgdf sg dfg 2024
gddgds es dg 2023 dgd ggdsgd
gddgds es dg 2024 dgd ggdsgd
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
13.10.2023, 17:26
Ответы с готовыми решениями:

Исправить ошибку регулярного выражения на номер телефона qiwi API
qiwi дает вот такое регулярное выражение на номер телефона ^tel:\+\d{1,15}$ телефон приходит постом в формате...

Вводится номер месяца 2006 года. Определить время года, которому соответствует этот месяц
Перевод программы с паскаль на сишарп Вводится номер месяца. Определить время года, которому соответствует этот месяц. (Использовать...

Заданы число и месяц невисокосного года. Вычислить порядковый номер даты, начиная отсчет с начала года
Заданы два натуральных числа a,b которые обозначают число и месяц не високосного года. Вычислить порядковый номер даты, начиная отсчет с...

14
Любознательный
 Аватар для YuS_2
7405 / 2255 / 360
Регистрация: 10.03.2016
Сообщений: 5,216
13.10.2023, 17:55
Цитата Сообщение от Gdasar Посмотреть сообщение
Код ниже работает, когда год встречается в начале строки. Остальные два случая он не обрабатывает. Помогите разобраться.
1.
re.match(pattern, string, flags=0)
If zero or more characters at the beginning of string match the regular expression pattern
2. Зачем три шаблона для замены? Чем отличается расположение года в разных местах строки?

3. Каковы критерии замены:
"tretert ertet r2020 gdfgfg 2020"
на
"tretert ertet r2020 gdfgfg 2023"
и на
"tretert ertet r2020 gdfgfg 2024"
?
Почему две строки вместо одной? Почему в первом случае один год, а во втором другой?
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
13.10.2023, 18:18  [ТС]
Цитата Сообщение от YuS_2 Посмотреть сообщение
Почему две строки вместо одной? Почему в первом случае один год, а во втором другой?
Потому что строк на выходе должно быть столько, сколько элементов находится в NewYears. Получается из одной входной строки получаем N новых строк, где N - количество элементов в NewYears.

Добавлено через 7 минут
Цитата Сообщение от YuS_2 Посмотреть сообщение
Зачем три шаблона для замены? Чем отличается расположение года в разных местах строки?
Потому что я только такой алгоритм придумал. Я посчитал правильным обработать каждый случай по-своему. Если просто менять, например 2022 с помощью команды replace или ей подобным, то подобный алгоритм будет работать неправильно в таких случаях:
Code
1
номер детали 202220/4 произведено в 2021 году
С помощью replace получим:

номер детали 202320/4 произведено в 2023 году
номер детали 202420/4 произведено в 2024 году

А должны получить:

номер детали 202220/4 произведено в 2023 году
номер детали 202220/4 произведено в 2024 году

Именно поэтому я посчитал важным учитывать пробелы около номера года.
0
Любознательный
 Аватар для YuS_2
7405 / 2255 / 360
Регистрация: 10.03.2016
Сообщений: 5,216
13.10.2023, 20:16
Цитата Сообщение от Gdasar Посмотреть сообщение
Потому что строк на выходе должно быть столько, сколько элементов находится в NewYears. Получается из одной входной строки получаем N новых строк, где N - количество элементов в NewYears.
Так. С этим разобрались...

Цитата Сообщение от Gdasar Посмотреть сообщение
Я посчитал правильным обработать каждый случай по-своему.
Цитата Сообщение от Gdasar Посмотреть сообщение
поэтому я посчитал важным учитывать пробелы около номера года.
Тогда, это неправильно. Шаблон можно составлять с различными уточнениями... просмотр вперед, назад и т.д.
как пример:
Python
1
2
3
4
5
6
7
import re
 
NewYears = [2023, 2024]
s = 'деталь 2005 с номером втулки 2022 -20/4 произведено в 2021 году'
for i in NewYears:
    out = re.sub(r'\b\d{4}\b(?= *г)', f'{i}', s)
    print(out)
В общем, тут надо поработать над условиями сначала... а для этого необходимо иметь представление о возможном содержании текста, подаваемого на вход. В этом случае код можно значительно упростить...
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
13.10.2023, 20:28  [ТС]
Цитата Сообщение от YuS_2 Посмотреть сообщение
out = re.sub(r'\b\d{4}\b(?= *г)', f'{i}', s)
Алгоритм должен учитывать только те значения, которые заданы в OldYears. Именно конкретные числа.
Данная функция создана с сильным упрощением. На самом деле, заменять придётся не только номер года, но и произвольные слова, которые указаны в заранее заготовленном списке.

Добавлено через 6 минут
YuS_2, Ваш код работает некорректно.
Строка:
Code
1
деталь 2005 с номером втулки 2022 -20/4 произведено в 2021 году
Должна породить две строки, так как NewYears = [2023, 2024], следующего вида:
Code
1
2
деталь 2023 с номером втулки 2023 -20/4 произведено в 2023 году
деталь 2024 с номером втулки 2024 -20/4 произведено в 2024 году
0
Любознательный
 Аватар для YuS_2
7405 / 2255 / 360
Регистрация: 10.03.2016
Сообщений: 5,216
13.10.2023, 20:42
Цитата Сообщение от Gdasar Посмотреть сообщение
Алгоритм должен учитывать только те значения, которые заданы в OldYears. Именно конкретные числа.
Это не проблема.
Python
1
2
3
4
5
6
7
8
import re
 
OldYears = r'\b(?:20[0-1][0-9]|202[0-2])(?= *г)'
NewYears = [2023, 2024]
s = '2010г деталь 1999 2025 г с номером втулки 2022 -20/4 произведено в 2021 году'
for i in NewYears:
    out = re.sub(f'{OldYears}', f'{i}', s)
    print(out)
Цитата Сообщение от Gdasar Посмотреть сообщение
На самом деле, заменять придётся не только номер года, но и произвольные слова.
Потому и говорю, что над условиями надо поработать. Знание содержания текста - обязательное условие для составления оптимального кода и шаблонов регэкспов.
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
13.10.2023, 20:45  [ТС]
Суть задачи:
На вход подаётся 2 списка:
1) список слов, чисел и т.д - которые нужно заменить (OldYears)
2) список слов, чисел и т.д - на которые будем менять (NewYears)
Должен быть выбор, в какой позиции будут проходить замены. Если нужно в начале и конце - один вариант, нужно только в середине - второй, только в середине и в конце - третий и так далее. То есть, мы можем гибко настраивать место, где будет проходить замена. Для этого я и использовал 3 разных условия.

Каждая замена должна порождать N новых строк, где N - количество элементов в NewYears.

Если в строке были найдены несколько элементов, которые нужно заменить, то они меняются все разом на одно и тоже значение. Как пример:
Code
1
деталь 2005 с номером втулки 2022 -20/4 произведено в 2021 году
Получается:
Code
1
2
деталь 2023 с номером втулки 2023 -20/4 произведено в 2023 году
деталь 2024 с номером втулки 2024 -20/4 произведено в 2024 году
0
Любознательный
 Аватар для YuS_2
7405 / 2255 / 360
Регистрация: 10.03.2016
Сообщений: 5,216
13.10.2023, 20:45
Цитата Сообщение от Gdasar Посмотреть сообщение
Ваш код работает некорректно.
Мой код работает так, как и задумывался, т.е. корректно.
А чтобы он работал так, как нужно Вам, необходимо составить полное условие задачи и иметь представление о содержании текста, поступающего на вход
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
13.10.2023, 20:48  [ТС]
Цитата Сообщение от YuS_2 Посмотреть сообщение
Это не проблема.
Code
1
(?:20[0-1][0-9]|202[0-2])
- проблема.
Как я и написал: Алгоритм должен учитывать только те значения, которые заданы в OldYears. Именно конкретные числа. Можно задать любое число, не обязательно 4-х значное. Именно числа, а не диапазон чисел.
0
Любознательный
 Аватар для YuS_2
7405 / 2255 / 360
Регистрация: 10.03.2016
Сообщений: 5,216
13.10.2023, 20:54
Цитата Сообщение от Gdasar Посмотреть сообщение
Если в строке были найдены несколько элементов, которые нужно заменить, то они меняются все разом на одно и тоже значение.
Цитата Сообщение от Gdasar Посмотреть сообщение
Получается:
Не получается... потому, что:
Цитата Сообщение от Gdasar Посмотреть сообщение
деталь 2005
- здесь не год, а номер детали... этот пример был составлен специально, чтобы обратить Ваше внимание на возможные проблемы.

Добавлено через 5 минут
Gdasar, в вашей задаче присутствует конкретная проблема XY...
Если Вы желаете её решить, то необходимо вчитываться в предлагаемые способы её решения... у меня нет абсолютно никакого представления о задаче в целом. Вы же просили о помощи, в частичном её решении... опишите задачу полностью.

Цитата Сообщение от Gdasar Посмотреть сообщение
- проблема.
Как бы это сказать поточнее... это не проблема. Это регулярное выражение, которое работает ровно также, как и Ваш список:
Python
1
OldYears = [2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022]
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
13.10.2023, 20:55  [ТС]
Code
1
деталь 2005 с номером втулки 2022 -20/4 произведено в 2021 году
Не зависимо от смысла! Разве бредо-примеры из моего первого сообщения ни о чём не говорят.
0
Любознательный
 Аватар для YuS_2
7405 / 2255 / 360
Регистрация: 10.03.2016
Сообщений: 5,216
13.10.2023, 20:56
Цитата Сообщение от Gdasar Посмотреть сообщение
Можно задать любое число, не обязательно 4-х значное. Именно числа, а не диапазон чисел.
Описывайте задачу целиком, а не в час по чайной ложке, если таки помощь требуется.
0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
13.10.2023, 20:58  [ТС]
YuS_2, спасибо за помощь, больше не нужно, пожалуйста. Я лучше пойду с крыши сигану.

Добавлено через 1 минуту
Цитата Сообщение от Gdasar Посмотреть сообщение
Как я и написал: Алгоритм должен учитывать только те значения, которые заданы в OldYears. Именно конкретные числа. Можно задать любое число, не обязательно 4-х значное. Именно числа, а не диапазон чисел.
Цитата Сообщение от YuS_2 Посмотреть сообщение
Как бы это сказать поточнее... это не проблема. Это регулярное выражение, которое работает ровно также, как и Ваш список:
Совсем нет противоречия, совсем...

Добавлено через 47 секунд
Если я из списка удалю числа, что тогда?
0
Любознательный
 Аватар для YuS_2
7405 / 2255 / 360
Регистрация: 10.03.2016
Сообщений: 5,216
13.10.2023, 21:02

Не по теме:

Цитата Сообщение от Gdasar Посмотреть сообщение
Я лучше пойду с крыши сигану.
Цитата Сообщение от Gdasar Посмотреть сообщение
Совсем нет противоречия, совсем...
Ну, ты заходи... если что...


0
191 / 52 / 19
Регистрация: 18.02.2013
Сообщений: 508
Записей в блоге: 9
13.10.2023, 21:38  [ТС]
В общем, чтобы матчились регулярки, нужно вместо re.match использовать re.search.
А ларчик просто открывался. Не нужно усложнять и искать проблему там, где ее просто нет и не может быть.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
13.10.2023, 21:38
Помогаю со студенческими работами здесь

Выборка регулярного выражения
Добрый вечер, есть файл с содержимом такого вида(это шаблон) ...

Анализ регулярного выражения
Имеется регулярное выражение для вставки разделителя в числа. Например на входе 12345678 на выходе 12,345,678 function...

Шаблон регулярного выражения
Столкнулся с небольшой проблемой при изучении регулярных выражений. Написал код который, находит введенное слово(или точнее все его...

Понимание регулярного выражения
Добрый день ув. пользователи! Подскажите пожалуйста, что значит эта запись. preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/'

Составление регулярного выражения
Привет. Есть теги {group=8}Какой то текст{/group} Они разумеется в tpl файле который достаётся функцией в php файле. Задача...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru