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

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

13.10.2023, 17:26. Показов 549. Ответов 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
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,213
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
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,213
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
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,213
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
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,213
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
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,213
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
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,213
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
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,213
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
Ответ Создать тему
Новые блоги и статьи
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru