Найти - Пользователи
Полная версия: редактирование файла, добавление строк и нумерация
Начало » Python для новичков » редактирование файла, добавление строк и нумерация
1
z1g1zmund
Доброго времени суток, я в питоне начинающий..
есть такой файл “GameMenu.res”, из игры counter-strike 1.6, в нем описано главное меню игры..
Я хочу иметь возможность изменять его(не создавать новый, а именно редактировать существующий).
Состоит он из главного слова Gamemenu, затем фигурные скобки {}
в главных фигурных скобках находятся элементы меню, они пронумерованы и содержат в себе несколько строк, которые так же находятся в фигурных скобках.
https://ltdfoto.ru/images/12d07c80fa4af2cd49.png

как я могу работать с подобным файлом?
Я не прошу код, просто толкните в правильную сторону..
Я не понимаю каким образом можно добавить новый блок, и перенумеровать остальные блоки.
Добавлять блоки нужно сверху, то-есть добавленный блок должен быть под номером 1:
“1”
{



}
Я могу так сделать, но получится 2 блока с названием “1”.

Я надеюсь внятно всё объяснил. Заранее благодарю.
py.user.next
z1g1zmund
есть такой файл “GameMenu.res”, из игры counter-strike 1.6
Приведи файл точно. Используй теги code. Либо пиши через https://pastebin.com .

1. Выложи файл, который подаётся на вход программы.
2. Выложи файл, который получается на выходе программы из входного файла.
3. Дальше можно начинать писать программу для этих файлов, которой ещё нет.
z1g1zmund
py.user.next


оригинальный
 "GameMenu"
{
"1"
{
"label" "#GameUI_GameMenu_ResumeGame"
"command" "ResumeGame"
"OnlyInGame" "1"
}
"2"
{
"label" "#GameUI_GameMenu_Disconnect"
"command" "Disconnect"
"OnlyInGame" "1"
"notsingle" "1"
}
"4"
{
"label" "#GameUI_GameMenu_PlayerList"
"command" "OpenPlayerListDialog"
"OnlyInGame" "1"
"notsingle" "1"
}
"8"
{
"label" ""
"command" ""
"OnlyInGame" "1"
}
"9"
{
"label" "#GameUI_GameMenu_NewGame"
"command" "OpenCreateMultiplayerGameDialog"
}
"10"
{
"label" "#GameUI_GameMenu_FindServers"
"command" "OpenServerBrowser"
}
"11"
{
"label" "#GameUI_GameMenu_Options"
"command" "OpenOptionsDialog"
}
"12"
{
"label" "#GameUI_GameMenu_Quit"
"command" "Quit"
}
}


измененный
"GameMenu"
{
"1"
{
"label" "Конфиг с.cfg"
"command" "engine exec c.cfg"
}

"2"
{
"label" ""
"command" ""
}

"3"
{
"label" ""
"command" ""
}

"4"
{
"label" "#GameUI_GameMenu_ResumeGame"
"command" "ResumeGame"
"OnlyInGame" "1"
}
"5"
{
"label" "#GameUI_GameMenu_Disconnect"
"command" "Disconnect"
"OnlyInGame" "1"
"notsingle" "1"
}
"6"
{
"label" "#GameUI_GameMenu_PlayerList"
"command" "OpenPlayerListDialog"
"OnlyInGame" "1"
"notsingle" "1"
}
"7"
{
"label" ""
"command" ""
"OnlyInGame" "1"
}
"8"
{
"label" "#GameUI_GameMenu_NewGame"
"command" "OpenCreateMultiplayerGameDialog"
}
"9"
{
"label" "#GameUI_GameMenu_FindServers"
"command" "OpenServerBrowser"
}
"10"
{
"label" "#GameUI_GameMenu_Options"
"command" "OpenOptionsDialog"
}
"11"
{
"label" "#GameUI_GameMenu_Quit"
"command" "Quit"
}
}
py.user.next
Тут надо работать просто с текстом.

Это надо сначала входной файл разделить на блоки по строкам. Типа заголовок, тело, подвал. Потом тело нужно разделить на блоки тоже по строкам. Блоком будет являться последовательность строк от цифрового названия в двойных кавычках до закрывающей фигурной скобки. После того как ты разделил, у тебя получается список блоков тела. И вот в этот список ты начинаешь вставлять дополнительные блоки (в начало, в конец, в середину, неважно куда). После того, как ты вставил блоки, ты запускаешь перенумератор, который просто заходит в каждый блок в этом списке и заменяет цифровое название блока на номер по порядку. После перенумерации у тебя есть заголовок всего файла, тело файла в виде списка перенумерованных блоков, подвал файла. И дальше ты это всё выводишь в отдельный файл вывода друг за другом. Так у тебя получается файл вывода. После этого ты берёшь файл ввода и удаляешь, а файл вывода переименовываешь в файл ввода. И так у тебя получается изменённый файл.

Сделаешь ли ты это сам на питоне? Ну, хрен знает, не думаю. Тут надо много функций всяких написать, которые и будут это дробить на блоки, перенумеровывать каждый блок, эти строчки искать для накопления блока. Без опыта, я не думаю, что ты напишешь хоть что-то приемлемое.

z1g1zmund
Я не прошу код, просто толкните в правильную сторону.
Это ты попросил тебя направить.

Может быть, xam1816 это напишет. Но я тоже тут не уверен, что оно красиво получится. Просто писать надо так, чтобы при изменении каких-то вводных требований код не приходилось писать заново весь, а достаточно было добавить одну строчку. А такие коды он ещё писать не умеет.

Так что попробуй сам. Может, докуда-то и дойдёшь сам. Но потом выложишь сюда результат. И если нифига не будет решений, я посмотрю. Для меня-то это простая фигня, я такие писал сто раз.
doza_and
py.user.next
Но я тоже тут не уверен, что оно красиво получится.
Да, красивых решений тут похоже не получится.
py.user.next
Просто писать надо так, чтобы при изменении каких-то вводных требований код не приходилось писать заново весь

Из постановки задачи непонятно почему ТС не может это ручками один раз сделать.
Можно предложить несколько вариантов кривых решений в той или иной степени не универсальных.


1 Нумерацию сдвинуть легко регулярными выражениями, если в качестве замены подать функцию. А вкорячить потом после второй строки свой блок не проблема.

2. Если регулярками понавставлять двоеточий и запятых то из скобок получится или json или модуль который можно импортировать (в последнем случае не обязательно убирать конечные запятые). Но не факт что записав json и убрав запятые и двоеточия получим читаемое игрой содержимое.

py.user.next
doza_and
Да, красивых решений тут похоже не получится.
Да я не думаю, что тут надо дерево строить. Можно всё сделать, построив просто плоскую структуру. Плоскую структуру с вложенной плоской структурой. Очень всё просто получится. Просто xam1816'у не хватит опыта. По задаче с выписками из ЕГРН это видно.

doza_and
Из постановки задачи непонятно почему ТС не может это ручками один раз сделать.
Наверное, вероятность того, что он не может это делать руками, высокая. Видимо, он делает это много раз или просто часто.
Да я и сам делал такое. А связано это было с тем, что при обновлении софта или переустановке все старые настройки стирались и становились дефолтными и надо было заново всё настраивать и писать везде. Так вот лучше это всё делать скриптом за секунду, чем сидеть полдня и перепроверять, всё ли правильно отредактировано уже в десятый раз по одному кругу.

doza_and
1 Нумерацию сдвинуть легко регулярными выражениями, если в качестве замены подать функцию.
Дело в том, что завтра он скажет, что ему надо теперь блоки в середину вставлять. И тут-то простой сдвиг нумерации превратится в тыкву. Придётся тогда заново всё писать и делать уже всё по-нормальному. Так вот нумерацию можно проводить любым образом тогда, когда у тебя есть что нумеровать в виде такого составного объекта, состоящего из объектов, и над этим объектом можно построить путём расширения разные операции. Составной объект, который состоит из маленьких объектов. Так вот на этом составном объекте можно добавить его операцию перенумерации, которая при выполнении итеративно запускает у каждого маленького объекта его личную перенумерацию самого себя.

doza_and
Если регулярками понавставлять двоеточий и запятых то из скобок получится или json
Да соблазн такой есть. Но это мнимое спасение. Оно сильно исказит исходный файл. Оно может табуляцию, например, заменить на пробелы или вообще стереть всё нафиг, превратив в одну строку весь файл. И тут-то вдруг и окажется, что этот Counter Strike не может понять этот файл, потому что ждёт там блоками всё и с табуляциями. Ну, или там просто всё это станет нечитаемым человеком, а нужно, чтобы оно было читаемым и меняемым руками в том числе - чтобы и скриптом можно было всё поменять, и руками.

Тут я набросал пример
  
>>> import re
>>> 
>>> class Document:
...     def __init__(self, header, body, footer):
...         self.header = header
...         self.body = body
...         self.footer = footer
...     def __str__(self):
...         return '{}\n{}\n{}'.format(
...             self.header,
...             self.body,
...             self.footer
...         )
... 
>>> class DocumentHeader:
...     def __init__(self, text):
...         self.text = text
...     def __str__(self):
...         return 'header {{\n\t{}\n'.format(self.text)
... 
>>> class DocumentBody:
...     def __init__(self, blocks):
...         self.blocks = blocks
...     def __str__(self):
...         return '\n'.join(map(str, self.blocks))
...     def rename_blocks(self):
...         for block in self.blocks:
...             block.rename_to_number_add_1()
...             block.rename_to_number_width(3)
...             block.rename_to_prefix('<')
...             block.rename_to_suffix('>')
... 
>>> class DocumentBodyBlock:
...     def __init__(self, name, text):
...         self.name = name
...         self.text = text
...     def __str__(self):
...         return ('\tblock "{}" {{\n'
...                 '\t\t{}\n'
...                 '\t}}').format(self.name, self.text)
...     def rename_to_prefix(self, text):
...         self.name = text + self.name
...     def rename_to_suffix(self, text):
...         self.name = self.name + text
...     def rename_to_number_add_1(self):
...         self.name = re.sub(
...             r'\d+',
...             lambda mo: str(int(mo.group()) + 1),
...             self.name
...         )
...     def rename_to_number_width(self, n):
...         self.name = '{:0{w}d}'.format(int(self.name), w=n)
... 
>>> class DocumentFooter:
...     def __init__(self, text):
...         self.text = text
...     def __str__(self):
...         return '\n\t{}\n}} footer'.format(self.text)
... 
>>> body_blocks = (
...     DocumentBodyBlock('1', 'block text 1'),
...     DocumentBodyBlock('2', 'block text 2'),
...     DocumentBodyBlock('3', 'block text 3'),
...     DocumentBodyBlock('4', 'block text 4'),
...     DocumentBodyBlock('5', 'block text 5')
... )
>>> body = DocumentBody(body_blocks)
>>> 
>>> document = Document(
...     DocumentHeader('header text'),
...     body,
...     DocumentFooter('footer text')
... )
>>> 
>>> out = str(document)
>>> print(out)
header {
        header text
 
        block "1" {
                block text 1
        }
        block "2" {
                block text 2
        }
        block "3" {
                block text 3
        }
        block "4" {
                block text 4
        }
        block "5" {
                block text 5
        }
 
        footer text
} footer
>>> 
>>> body.rename_blocks()
>>> 
>>> out = str(document)
>>> print(out)
header {
        header text
 
        block "<002>" {
                block text 1
        }
        block "<003>" {
                block text 2
        }
        block "<004>" {
                block text 3
        }
        block "<005>" {
                block text 4
        }
        block "<006>" {
                block text 5
        }
 
        footer text
} footer
>>>
Здесь сформирована структура документа, над которой определены операции. Таким образом мы можем получить один документ, потом провести над ним какие-то операции и получить из него другой документ. Естественно, таких документов можно наделать много разных. И потом мы можем брать информацию из одного такого документа с помощью его операций, затем трансформировать эти данные и затем передавать эту новую информацию в другой документ и записывать в него с помощью его операций.

Да, и это не ООП. Это просто абстрагирование и агрегирование объектов, не более. То есть это ерунда на школьном уровне.
xam1816
 class Document:
    def __init__(self, name):
        self.name = name
        self.blocks = []
    def __str__(self):
        return '"{name}"\n{{\n{blocks}\n}}'.format(name=self.name, blocks=self.form_blocks())
#
    def form_blocks(self):
        text = ''.join(['\t"{}"\n{}'.format(n,str(b)) for n, b in enumerate(self.blocks, 1)])
        return text
#
d = Document('GameMenu') # создаем документ без блоков
print(d)
print("===============================")
#
class Block:
    def __init__(self,**kwargs):
        self.kwargs = kwargs
#
    def __str__(self):
        text = '\n'.join(['\t\t"{}" "{}"'.format(k, v) for k, v in self.kwargs.items()])
        out = '\t{{\n{}\n\t}}\n'.format(text)
        return out
#
b = Block(label='GameUI_GameMenu_Disconnect',command='Disconnect') # создаем блок
b2 = Block(label='GameUI_GameMenu_NewGame',command='OpenCreateMultiplayerGameDialog',OnlyInGame='1')
#
d.blocks.append(b) # добавляем в список блоков документа
d.blocks.append(b2) # добавляет следующий блок в конец списка
#
print(d)
print("===============================")
#
b3 = Block(label='Конфиг с.cfg',command='engine exec c.cfg')
d.blocks.insert(0,b3) # вставляет новый блок в начало списка
#
print(d)
print("===============================")
#
d.blocks.insert(1,d.blocks.pop(0)) #перемещает с первого места на второе
print("===============================")
#
print(d)

вывод
 "GameMenu"
{
}
===============================
"GameMenu"
{
	"1"
	{
		"label" "GameUI_GameMenu_Disconnect"
		"command" "Disconnect"
	}
	"2"
	{
		"label" "GameUI_GameMenu_NewGame"
		"command" "OpenCreateMultiplayerGameDialog"
		"OnlyInGame" "1"
	}
}
===============================
"GameMenu"
{
	"1"
	{
		"label" "Конфиг с.cfg"
		"command" "engine exec c.cfg"
	}
	"2"
	{
		"label" "GameUI_GameMenu_Disconnect"
		"command" "Disconnect"
	}
	"3"
	{
		"label" "GameUI_GameMenu_NewGame"
		"command" "OpenCreateMultiplayerGameDialog"
		"OnlyInGame" "1"
	}
}
===============================
===============================
"GameMenu"
{
	"1"
	{
		"label" "GameUI_GameMenu_Disconnect"
		"command" "Disconnect"
	}
	"2"
	{
		"label" "Конфиг с.cfg"
		"command" "engine exec c.cfg"
	}
	"3"
	{
		"label" "GameUI_GameMenu_NewGame"
		"command" "OpenCreateMultiplayerGameDialog"
		"OnlyInGame" "1"
	}
}
Process finished with exit code 0
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