Замена кусков текста в выделенных файлах

Обсуждение вопросов автоматизации Total Commander с помощью сторонних программ и скриптовых технологий.

Модераторы: Avada, CaptainFlint, Nik, d-view, Моторокер

Samwatas
Сообщения: 95
Зарегистрирован: Сб сен 12, 2009 20:26

Сообщение Samwatas »

Rodny писал(а): P.P.S. Поскольку с AutoIt'ом сталкиваться ещё не доводилось, ставить/компилировать несколько напряжно, если можно будет обойтись vbs, это предпочтительнее.
Напрасно, в АвтоИте есть функции предназначенные специально для работы с секциями ИНИ-файлов, как виндовые АПИ (поэтому написать такой скрипт будет легче всего).
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

Loopback
Да Бог с тобой, какая экселевская.. :D Я о расположении самих окошек говорю с левой стороны. Комбинации(строка/столбец): 1x2, 2x2, 3x2, 3x3. В строку тоже ничего, но так, действительно, растянется по высоте. Если другого не дано, то, что тут поделаешь.. :)
Окно справа пусть целиком до низа будет растянуто, если можно.
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

Flasher писал(а):Так, окей, уже лучше, а что с табуляцией делать?
Хм, ну тогда:

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

With CreateObject("TCScript.Helper") 
  .SetTextToClip(Replace(Replace(.GetTextFromClip, vbNewLine, "\n"), vbTab, "\t")) 
End With

...

Find_String = Replace(Replace(Find_String, "\n", vbNewLine), "\t", vbTab)

...

Replace_String = Replace(Replace(Replace_String, "\n", vbNewLine), "\t", vbTab)
Последний раз редактировалось Batya Вт окт 05, 2010 17:42, всего редактировалось 1 раз.
Нет, я не сплю. Я просто медленно моргаю.
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

Rodny писал(а):У меня проблема в том, что я точно знаю только название секции, т. е. я не могу здесь задать строки для поиска.
А что мешает открыть оба инишника и скопипастить целиком секции в каждое окошко и осуществить замену? Или это так часто требуется?
Добавлено: хотя нет, я тут подумал, что этот способ мало отличим от замены ручками в редакторе. Тогда, конечно, нужно искать другой способ.
Batya писал(а):

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

.SetTextToClip(Replace(Replace(.GetTextFromClip, vbNewLine, "\n")), vbTab, "\t"))
Что-то на скобки ругается, не пойму почему. :?
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

Flasher писал(а):Что-то на скобки ругается
Исправил.
Нет, я не сплю. Я просто медленно моргаю.
Аватара пользователя
Rodny
Сообщения: 949
Зарегистрирован: Ср янв 24, 2007 00:59
Откуда: Могилёв, Беларусь

Сообщение Rodny »

Samwatas писал(а):Напрасно, в АвтоИте есть функции предназначенные специально для работы с секциями ИНИ-файлов, как виндовые АПИ (поэтому написать такой скрипт будет легче всего).
Похоже на то. То, что я поначалу принял за решение, оказалось функциями для VB(A), использующими соответствующие из WinAPI. В VBS, насколько я понял, с этим туго, народ построчно файлы перебирает.

Граждане АвтоИтовцы, если не трудно?..
Samwatas
Сообщения: 95
Зарегистрирован: Сб сен 12, 2009 20:26

Сообщение Samwatas »

Ставь конкретней задачу: с какими параметрами желаешь вызывать утиль, где хранить имя (имена) секции(й) (можно тоже в ини-файле, только в своём, а при старте утилиты подгружать), поведение утилиты при отклонениях от плана (например в первом файле не оказалось секции с данным именем, или секция пустая) и т.д.
В общем чем подробнее, тем лучше (может тебе хотелось бы видеть какие-то дополнительные опции).
Последний раз редактировалось Samwatas Вт окт 05, 2010 18:16, всего редактировалось 2 раза.
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

Rodny писал(а):В VBS, насколько я понял, с этим туго, народ построчно файлы перебирает.
Если у тебя установлен TCScript.Helper, то можешь воспользоваться демо-скриптом DemoScripts\ReadWriteSection.vbs, идущим вместе со TCScript.Helper.
Нет, я не сплю. Я просто медленно моргаю.
Samwatas
Сообщения: 95
Зарегистрирован: Сб сен 12, 2009 20:26

Сообщение Samwatas »

Без проверок на ошибки и доп. опций скрипт занимает 1 строчку:

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

IniWriteSection("C:\Temp2.ini", "section2", IniReadSection("C:\Temp1.ini", "section1"))
C:\Temp1.ini - первый инишник, из которого мы будем читать секцию.
C:\Temp2.ini - второй инишник, в который мы будем писать секцию.
section1 - имя секции, которую мы будем читать из первого файла.
section2 - имя секции, в которую мы будем писать во втором файле (может совпадать с именем первой секции, если необходимо, а может иметь и другое имя).
Если секцию во втором файле требуется предварительно удалить, то есть функция IniDelete("filename", "section") - просто вставь её первой в скрипт (естественно, прописав нужное имя файла и секции).

П.С. Тут кто-то недавно говорил, что все скриптовые языки имеют примерно равный функционал. Ну-ну..
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

Flasher
Ну вот, последний на сегодня вариант :) Параметры интерфейса можно задать в начале скрипта, думаю там все понятно.

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

#include <GUIConstantsEx.au3> 

If $CmdLine[0] < 1 Then 
    MsgBox (0, "", "Недостаточно параметров, должен быть 1.") 
    Exit 
EndIf 

; ================================
; Настройки отображения интерфейса
; ================================ 
; Число полей поиска
Global Const $gSrcCount = 3
; Высота одного поля
Global Const $gSrcHeight = 120
; ================================

Global $aList  = _TCHLoadFileList($CmdLine[1]) 
Global $gReplaces = 0, $gMask
Global $gSrcEdit[$gSrcCount]
Global $nGUIHeight = $gSrcHeight * $gSrcCount + 109

$hGUI = GUICreate("Поиск и замена", 563, $nGUIHeight, -1, @DesktopHeight/2 - $nGUIHeight/2)
GUICtrlCreateLabel("Маска файлов", 8, 6, 78, 17) 
$edMask = GUICtrlCreateInput("*.*", 8, 24, 265, 21) 
GUICtrlCreateLabel("Текст для поиска", 8, 54, 94, 17) 
GUICtrlCreateLabel("Текст для замены", 288, 54, 98, 17) 

For $i = 0 To $gSrcCount - 1
    $gSrcEdit[$i] = GUICtrlCreateEdit("", 8, 72 + $gSrcHeight * $i, 265, $gSrcHeight)
Next

$edTrg = GUICtrlCreateEdit("", 288, 72, 265, $gSrcHeight * $gSrcCount)
$cbCaseSence = GUICtrlCreateCheckbox("Учитывать регистр", 8, $gSrcHeight * $gSrcCount + 84, 137, 17) 
$btnOK = GUICtrlCreateButton("OK", 400, $gSrcHeight * $gSrcCount + 79, 75, 25) 
$btnCancel = GUICtrlCreateButton("Отмена", 480, $gSrcHeight * $gSrcCount + 79, 75, 25)
GUISetState(@SW_SHOW) 

If $aList[0] = 0 Then GUICtrlSetState($btnOK, $GUI_DISABLE) 

While 1 
   $nMsg = GUIGetMsg() 
   Switch $nMsg 
      Case $GUI_EVENT_CLOSE, $btnCancel 
        Exit 
      Case $btnOK 
        $gMask = _MaskToRegexp(GUICtrlRead($edMask)) 
        For $i = 1 To $aList[0] 
            If StringRight($aList[$i], 1) = "\" Then 
                _DoFolder($aList[$i]) 
            Else 
                _DoFile($aList[$i]) 
            EndIf 
        Next 
        MsgBox (0, "", "Выполнено замен: " & $gReplaces, 0, $hGUI) 
        Exit 
   EndSwitch 
WEnd 

Func _DoFolder($sFolder) 
    If $sFolder = "" Then Return 
    Local $sDirs = "" 
    Local $hSearch = FileFindFirstFile($sFolder & "*.*") 
    If @error Then Return 
    While 1 
        $sFile = FileFindNextFile($hSearch) 
        If @error Then ExitLoop 
        If @extended Then 
            $sDirs &= $sFolder & $sFile & "\" & @LF 
            ContinueLoop 
        EndIf 
        _DoFile($sFolder & $sFile) 
    Wend 
    FileClose($hSearch) 
    ; Обработку каталогов приходится делать отдельно, 
    ; чтобы не оставлять открытый поисковый хэндл, 
    ; их максимально может быть 64 
    $aDirs = StringSplit($sDirs, @LF) 
    For $i = 1 To $aDirs[0] 
        _DoFolder($aDirs[$i]) 
    Next 
EndFunc 

Func _DoFile($sFile) 
    If StringRegExp($sFile, $gMask) = 0 Then Return 
    Local $sText = FileRead($sFile)
    Local $sSrc
    MsgBox(0, "title", $sText)
    Local $nReplaces = 0
    For $i = 0 To $gSrcCount - 1
        $sSrc = GUICtrlRead($gSrcEdit[$i])
        If $sSrc = "" Then ContinueLoop
        $sText = StringReplace($sText, $sSrc, GUICtrlRead($edTrg), 0, _ 
                               BitAND(GUICtrlRead($cbCaseSence), $GUI_CHECKED))
        $nReplaces += @extended
    Next
    If $nReplaces = 0 Then Return
    $gReplaces += $nReplaces
    Local $hFile = FileOpen($sFile, 2) 
    FileWrite($hFile, $sText) 
    FileClose($hFile)
EndFunc 

Func _MaskToRegexp($sMask) 
    $sMask = StringRegExpReplace($sMask, "(\\|\.|\+|\^|\(|\)|\[|\]|\{|\}|\$)", "\\\1") 
    $sMask = StringReplace($sMask, "?", ".") 
    $sMask = StringReplace($sMask, "*", ".+?") 
    Return("(?i)^" & $sMask & "$") 
EndFunc 

Func _TCHLoadFileList($sFileName) 
    Local $asList[1] = [0] 
    Local $hfList = FileOpen($sFileName, 0) 
    While 1 
        $sLine = FileReadLine($hfList) 
        If @error Then Exitloop 
        ReDim $asList[UBound($asList)+1] 
        $asList[UBound($asList)-1] = $sLine 
    Wend 
    FileClose($hfList) 
    $asList[0] = UBound($asList)-1 
    Return $asList 
EndFunc
Аватара пользователя
Rodny
Сообщения: 949
Зарегистрирован: Ср янв 24, 2007 00:59
Откуда: Могилёв, Беларусь

Сообщение Rodny »

Batya
Спасибо, самое то. Надо будет всё-таки прочитать ридми дальше, чем до SendCommand :oops:

Samwatas
Спасибо, для моих скромных нужд хелпера пока вполне хватит. У меня мало-мальски опыт с VB есть, а вот на знакомство с автоитом пока времени взять негде.
Аватара пользователя
Lev
Сообщения: 392
Зарегистрирован: Ср мар 02, 2005 16:34

Сообщение Lev »

Lev
Дык, по-моему, тоже со строками только работает.
По-твоему.
Переведи на русский слово Multiline.
Ответь на вопрос - зачем в регекспах всякие: ^ Line start, $ Line end, \r, \n при построчной работе?
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

Loopback
С таблицей, я так понял, не получилось, жаль.
Loopback писал(а):Параметры интерфейса можно задать в начале скрипта, думаю там все понятно.
Э..э, а как же?:
Flasher писал(а):хотелось бы (если это возможно) разбивать левое окно на заданное в параметрах кол-во частей
Я же не буду для каждого случая компилить a3x-файл :) .
:idea: А ещё лучше, если сперва будет появляться маленькое окошко с 6-9 кнопочками с номерами, при нажатии на каждое из которых будет появляться окно, где левая часть разбита на сопоставленное с номером кол-во частей.

Lev
Ок, с этим всё понятно. Если есть возможность, сделай скрипт по аналогии со скриптом Volniy(+Batya) с использованием VBScript.RegExp и objRegExp.Multiline, а мы оценим.
Samwatas
Сообщения: 95
Зарегистрирован: Сб сен 12, 2009 20:26

Сообщение Samwatas »

Скопируй содержимое файла GUIConstantsEx.au3 в свой файл скрипта (можно также проредить его, удалив неиспользуемые константы), соответственно не нужно будет ничего компилить.
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

Это ситуацию никак не изменит, фактически будут те же грабли по временным затратам.
Ответить