Исключить определенные диапазоны из строки при замене регулярным выражением в PythonPython

Программы на Python
Ответить Пред. темаСлед. тема
Гость
 Исключить определенные диапазоны из строки при замене регулярным выражением в Python

Сообщение Гость »


У меня такая проблема.
Предположим, есть довольно длинный и сложный текстовый файл, в котором в разделителях можно встретить такие специальные блоки (которые могут быть пустыми):

Код: Выделить всё

some text
----
text inside special block
----
some text
----
----
some text
----
text inside special block
----
The task is to make some substitutions in the whole text but exclude text inside these borders () from these substitutions.
So for example we need to replace all substrings with strings but not inside special blocks. The result should be:

Код: Выделить всё

some TEXT
----
text inside special block
----
some TEXT
----
----
some TEXT
----
text inside special block
----
We cannot use lookahead or lookbehind here because in the given position we don't know if we are inside the special block or not (delimiters are not oriented).
So what I really do to solve this is first I parse the whole text for delimiters of special blocks then I get the indexes of "bad" lines and then I apply my regex substitutions line by line checking if this line is not one of the "bad" lines. But if my regex must apply to more than one line it becomes more complicated. And I'm sure there are some pretty smart and easy ways to handle this.
So basically what I need is to be able to exclude some fragments of the text (by theirs spans) from the when it applies to the whole text. Even if the regex only intersects with the span (not necessarily contains it). So that I can apply the first regex, take the spans of specials blocks by their begin and end indexes and exclude these spans from the second regex. How is this possible?
Right now I have this solution (the example above is simplified, sorry):

Код: Выделить всё

def find_code_lines(data):
# Search for blocks by regex They can be empty!
r = re.compile(r'(\n----(?=\n)(?P[\s\S]*?\n)----\n)')

# Delete all '\n' which are not line breaks (there are some of them in formulas etc.)
data_edited = data.replace('\\n', '')

# Save spans by symbol indexes
char_spans = []
for m in r.finditer(data_edited):
#print(m.span(1))
#print(m.span[1])
char_spans.append(m.span(1))

# Calculate spans by line indexes
line_spans = []
for span in char_spans:
begin = data_edited[:span[0]].count("\n") + 2
end = data_edited[:span[1]].count("\n") - 1
line_spans.append((begin, end))

return line_spans

# Check if index is inside one of spans
def in_spans(spans, line_index):
res = False
for span in spans:
if line_index >= span[0] and line_index < span[1]:
res = True
return res

# Parse text by blocks
code_lines = find_code_lines(data)

lines_edited = []
data_lines = data.splitlines()
replace_count = 0
for i in range(len(data_lines)):
if in_spans(code_lines, i):
lines_edited.append(data_lines[i])
#print('line in spans:', i)
else:
data_tuple = re.subn(r'(?P\s|^|\s\()\$(?P[^\$`\r\n]{1,1000}?)\$',
r'\1stem:[\2]',
data_lines[i])
if data_tuple[1] == 0:
lines_edited.append(data_lines[i])
else:
lines_edited.append(data_tuple[0])
replace_count += data_tuple[1]
lines_edited.append('')
data = '\n'.join(lines_edited)
log_it('Replaced Math blocks', replace_count)
UPD
I added more text to the input example because some of the solutions below can handle only specific versions of inputs (which are easier). So the most difficult one so far is like this:

Код: Выделить всё

some text
----
text inside special block
----
some text
----
----
some text
----
text inside special block
----
some text
Expected output:

Код: Выделить всё

some TEXT
----
text inside special block
----
some TEXT
----
----
some TEXT
----
text inside special block
----
some TEXT


Источник: https://stackoverflow.com/questions/781 ... sion-in-py
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»