Найти - Пользователи
Полная версия: Обработка текста для чайника... Подскажите?
Начало » Python для новичков » Обработка текста для чайника... Подскажите?
1 2
od4honnor
Значит так, ногами не пинать, табуретками не кидать, громко матом не ругаться… )))

Программеры уехали и вообще давно выходные… Так что помощи просить не у кого…

Есть пользовательская программа, данные с нее скинуты в текстовый файл.

В текстовом файле находятся описания обьектов в виде:

parameter10 0, 3000, 0, 300, 300, 3000

Для каждого обьекта таких параметров штук 20-30…

Сами текстовые файлы очень большие, руками исправлять не вариант…

Задача:

_СВОИМИ СИЛАМИ_ найти\создать инструмент чтобы исправить в текстовом файле один единственный параметр для каждого обьекта, например поделить все значения (кроме первого!) на пять или шесть…

Было
parameter10 0, 3000, 0, 300, 300, 3000

Стало
parameter10 0, 500, 0, 50, 50, 500

Причем не факт, что 3-е значение будет равно нулю, или что 4-5 значения будут не нулевые…

Все значения должны быть строго _целыми_ числами, то есть должен присутствовать механизм округления…

И загрузить этот текстовый файл назад в программу, чтобы она пересчитала все под новые данные…

Чего делать? Как решать проблему?

Добавлено.

Единственное, что удалось найти - вот этот плагин Питона http://sourceforge.net/projects/npppythonscript/ для http://notepad-plus-plus.org

Через дискуссию отсюда:
http://sourceforge.net/p/notepad-plus/discussion/1290590/thread/cc1b13c6/

http://sourceforge.net/p/npppythonscript/discussion/1199074/thread/8d2ed95a

Где давался следующий пример:
# Demo to use the results of a function as the replacement text.
# We'll search for 'N' followed by a number, and return a string with
# 'D' followed by the number doubled.
# So, The text "This is N32 which references N15" 
# Will become  "This is D64 which references D30"
# The replacement function gets a Regex Match object as a parameter
# and returns the complete replacement string. 
# Therefore, in this example, m.group(1) is the first matching group 
# (in this case the number), and m.group(0) is always the entire found string
# (so in this case N[number])
def replace_func(m):
    try:
        return 'D' + str(int(m.group(1)) * 2)
    except:
        return m.group(0)
editor.pyreplace('N([0-9]+)', replace_func)
А как это все адаптировать под себя? Я же не программист ни разу…

В примере ищут первое же совпадение “буква N + любая цифра” и начинают обрабатывать букву (удаляя ее) и умножая цифру на два, здесь же ситуация куда сложнее и такой “познаковый” подход не сработает…
dimy44
re.sub поможет. Вот пример
import re
text = """
parameter10 0, 3000, 0, 300, 300, 3000
parameter10 150, 3000, 10, 3300, 1300, 9000
parameter10 0, 6000, 0, 300, 300, 6000
"""
pattern = r'(?s)(?<![A-Za-z])([, ]+)(\d+)'
def fsub(mathobj):
    return '%s%s' % (mathobj.group(1), int(mathobj.group(2)) // 5)
text_new = re.sub(pattern, fsub, text)
print(text_new)
>>>

parameter10 0, 600, 0, 60, 60, 600
parameter10 30, 600, 2, 660, 260, 1800
parameter10 0, 1200, 0, 60, 60, 1200

>>>
py.user.next
>>> import re
>>> 
>>> s = """
... parameter10 0, 3000, 0, 300, 300, 3000
... parameter20 0, 3000, 0, 300, 300, 3000
... parameter10 0, 300, 0, 30, 30, 300
... parameter20 0, 300, 0, 30, 30, 300
... """
>>> 
>>> parn = 10
>>> divisor = 6
>>> 
>>> pat = r'^(parameter{0} )(.*)$'.format(parn)
>>> 
>>> tr_num = lambda mo: str(int(int(mo.group(0)) / divisor))
>>> tr = lambda mo: mo.group(1) + re.sub(r'\d+', tr_num, mo.group(2))
>>> 
>>> output = re.sub(pat, tr, s, count=0, flags=re.M)
>>> print(output)
 
parameter10 0, 500, 0, 50, 50, 500
parameter20 0, 3000, 0, 300, 300, 3000
parameter10 0, 50, 0, 5, 5, 50
parameter20 0, 300, 0, 30, 30, 300
 
>>>
od4honnor
dimy44
>>>

parameter10 0, 600, 0, 60, 60, 600
parameter10 30, 600, 2, 660, 260, 1800
parameter10 0, 1200, 0, 60, 60, 1200

>>>

первое значение изменять не нужно… там везде нули…

dimy44
re.sub поможет. Вот пример
А нельзя ли сделать вот через эту штуку?

editor.pyreplace('N([0-9]+)', replace_func)

Ведь у меня не Питон в чистом виде, а плагин скриптования для текстового редактора…

версия Питона в плагине:
Python 2.7.1 (release27-maint-npp, Feb 6 2011, 16:58:20)

И эта строка как раз отвечает за обработку всего текстового файла и его содержания… Она есть во всех примерах с форума плагина… И загонять мегабайтные файлы вместо трех строчек я не могу…

Зато программа округляет до целых чисел!!!

Правда если в одну из трех строчек примера забить parameter20 вместо parameter10 - она его тоже поделит…

py.user.next
>>> import re
>>>
>>> s = “”“
… parameter10 0, 3000, 0, 300, 300, 3000
… parameter20 0, 3000, 0, 300, 300, 3000
… parameter10 0, 300, 0, 30, 30, 300
… parameter20 0, 300, 0, 30, 30, 300
… ”“”
>>>
>>> parn = 10
>>> divisor = 6
>>>
>>> pat = r'^(parameter{0} )(.*)$'.format(parn)
>>>
>>> tr_num = lambda mo: str(int(int(mo.group(0)) / divisor))
>>> tr = lambda mo: mo.group(1) + re.sub(r'\d+', tr_num, mo.group(2))
>>>
>>> output = re.sub(pat, tr, s, count=0, flags=re.M)
>>> print(output)

parameter10 0, 500, 0, 50, 50, 500
parameter20 0, 3000, 0, 300, 300, 3000
parameter10 0, 50, 0, 5, 5, 50
parameter20 0, 300, 0, 30, 30, 300

>>>
Не работает… Сразу же ругается на синтаксис… В первой же строке…

>>> pat = r'^(parameter{0} )(.*)$'.format(parn)
Как я понимаю это аналог строки “parameter+10”???
Зачем уж так? Лишнее это… Пусть пользователь сам задает название параметра… Запутывает…
py.user.next
od4honnor
Не работает… Сразу же ругается на синтаксис… В первой же строке…
это вывод интерпретатора, нужно убрать “>>> ” и “… ” (используй sed)

od4honnor
Пусть пользователь сам задает название параметра
если есть параметры другого вида, то так и надо было написать
od4honnor
py.user.next
это вывод интерпретатора, нужно убрать “>>> ” и “… ”
извиняюсь… поправил - заработало…

py.user.next
если есть параметры другого вида, то так и надо было написать
опять моя вина…

Название параметра лучше задавать одной строчкой, названия всех параметров уникальные, хоть и одинаковые для всех обьектов… Вида “parameter_desyat”… Этого хватит…
od4honnor
py.user.next
(используй sed)
Да в курсе я и про sed, и про awk… Только там же, где шел разговор про них для подобных задач, упомянули и порекомендовали Notepad++…

Все-таки “дружелюбность” к обычному пользователю у него повыше…
dimy44
Аа, я подумал что первое значение идет после parameter. Тогда вот такой пример
import re
 
def text_new(text, div_value=5):
    f = lambda m: m.group(1) + str(int(m.group(2)) // div_value)
    return re.sub(r'(, )(\d+)', f, text)
 
text = """parameter10 0, 3000, 0, 300, 300, 3000
parameter11 0, 6000, 0, 300, 300, 6000"""
print(text_new(text, 6))
py.user.next
dimy44
Тогда вот такой пример
>>> import re
>>> 
>>> def text_new(text, div_value=5):
...     f = lambda m: m.group(1) + str(int(m.group(2)) // div_value)
...     return re.sub(r'(, )(\d+)', f, text)
... 
>>> text = """parameter10 12, 3000, 0, 300, 300, 3000
... parameter11 12, 6000, 0, 300, 300, 6000"""
>>> print text_new(text, 6)
parameter10 12, 500, 0, 50, 50, 500
parameter11 12, 1000, 0, 50, 50, 1000
>>>
1) не делит первое число
2) делит числа у параметра, у которого не надо делить
3) взял у тебя идею целочисленного деления ;) (совсем забыл про него)


od4honnor
Название параметра лучше задавать одной строчкой, названия всех параметров уникальные, хоть и одинаковые для всех обьектов
>>> import re
>>> 
>>> s = """
... parameter10 0, 3000, 0, 300, 300, 3000
... parameter20 0, 3000, 0, 300, 300, 3000
... parameter10 100, 300, 0, 30, 30, 300
... parameter20 100, 300, 0, 30, 30, 300
... """
>>> 
>>> parname = 'parameter10'
>>> divisor = 6
>>> 
>>> pat = r'^({0} )(.*)$'.format(parname)
>>> 
>>> tr_num = lambda mo: str(int(mo.group(0)) // divisor)
>>> tr = lambda mo: mo.group(1) + re.sub(r'\d+', tr_num, mo.group(2))
>>> 
>>> output = re.sub(pat, tr, s, count=0, flags=re.M)
>>> print(output)
parameter10 0, 500, 0, 50, 50, 500
parameter20 0, 3000, 0, 300, 300, 3000
parameter10 16, 50, 0, 5, 5, 50
parameter20 100, 300, 0, 30, 30, 300
>>>

od4honnor
упомянули и порекомендовали Notepad++
od4honnor
Все-таки “дружелюбность” к обычному пользователю у него повыше
в консоли просто пишешь
sed 's/....//'
и всё
dimy44
Тогда так:
import re
 
def text_new(text, div_value=5):
    f = lambda m: m.group(1) + str(int(m.group(2)) // div_value)
    return re.sub(r'( )(\d{2,}|[1-9])', f, text)
 
text = """parameter10 0, 3000, 0, 300, 300, 3000
parameter11 0, 6000, 0, 300, 300, 6000"""
print(text_new(text, 6))
хотя по поводу первого числа ТС писал что там и так всегда нули, так что в группу \1 запятую следовало бы вернуть.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB