Как в регулярных выражениях исключить из поиска нежелательные совпадения?

Добрый день. У меня есть следующее регулярное выражение:  
<pre><code>("originalText":")(&lt;i&gt;)*([A-Za-z0-9\(\) ',.!?-]+)(&lt;/i&gt;)*(","text":")(&lt;)*([А-Яа-я0-9A-Za-z\(\) ,.!?-]+)(&lt;/i&gt;\.|&lt;/i&gt;)*",</code></pre>  

Я использую его для замены текста в файле, который содержит 10 259 006 символов и является словарем перевода игры. К сожалению, машинный перевод сделал так, что теги <code>&lt;i&gt; &lt;/i&gt;</code> в русском тексте были повреждены или потеряны. Хотя данное регулярное выражение позволяет мне исправить большинство ошибок, оно также приводит к тому, что "здоровый" текст заменяется на себя же. Например, оно меняет:  
<pre><code>"originalText":"English text.","text":"Русский текст.",</code></pre>  
на  
<pre><code>"originalText":"English text.","text":"Русский текст.",</code></pre>  

Как мне можно исправить эту ситуацию?  

В частности, как исключить из поиска текст, в котором между <code>"originalText":"</code> и <code>","text":"</code> отсутствуют теги <code>&lt;i&gt;</code> или <code>&lt;/i&gt;</code>?  

Привожу примеры для пояснения:  
<pre><code>"originalText":"English text.","text":"Русский текст.",        - Этот текст должно пропустить
"originalText":"&lt;i&gt;English text.","text":"Русский текст.",     - Этот текст должно заменять
"originalText":"English text.&lt;/i&gt;","text":"Русский текст.",    - Этот текст должно заменять
"originalText":"&lt;i&gt;English text.&lt;/i&gt;","text":"Русский текст.", - Этот текст должно заменять</code></pre>  

К сожалению, у меня недостаточно знаний, чтобы составить подобное регулярное выражение.
  • 22 ноября 2024 г. 20:13
Ответы на вопрос 2
Чтобы ваше регулярное выражение заменяло только те строки, где присутствуют теги `<i>`, вам нужно добавить условие, которое позволит исключать строки, в которых нет этих тегов. 

Для этого можно использовать негативный просмотр (negative lookahead). Это позволит удостовериться, что между `originalText` и `text` есть хотя бы один из тегов `<i>`. Давайте попробуем изменить ваше регулярное выражение.

Вот пример модифицированного регулярного выражения:

```regex
("originalText":")(?=(?:[^<]*<i>[^<]*</i>)*[^<]*$)(&lt;i&gt;)*([A-Za-z0-9\(\) ',.!?-]+)(&lt;/i&gt;)*(","text":")(&lt;)*([А-Яа-я0-9A-Za-z\(\) ,.!?-]+)(&lt;/i&gt;\.|&lt;/i&gt;)*",
```

Разберем изменения:

- `(?=(?:[^<]*<i>[^<]*</i>)*[^<]*$)` – это позитивный просмотр, который проверяет, существуют ли в строке теги `<i>`. Он позволяет парсить только те строки, в которых присутствует хотя бы один тег.
- Стараемся избегать изменений в основной структуре вашего выражения, чтобы не сломать прежнюю логику.

Теперь ваше регулярное выражение будет работать только для строк, содержащих хотя бы один тег `<i>` между `"originalText":"` и `","text":"`.

Для тестирования, просто подставьте строки в регулярное выражение и проверьте, как оно будет работать. Убедитесь, что вы правильно используете флаги режима (например, `re.MULTILINE`), если это необходимо.

Если возникнут дополнительные вопросы или потребуется другая помощь, не стесняйтесь задавать!
Итак, у вас там файл в формате JSON. Это специальный машиночитаемый формат данных. Более правильное решение в вашем случае выглядит следующим образом: 
Т.о. вся работа сводится к работе с однозначным и конкретным куском текста. У вас классический случай Проблемы XY .
Похожие вопросы