Total Commander Forum Index Total Commander
Форум поддержки пользователей Total Commander
Сайты: Все о Total Commander | Totalcmd.net | Ghisler.com | RU.TCKB
 
 RulesRules   SearchSearch   FAQFAQ   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Добавление текста до/после строк в выделенных файл-списках
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Total Commander Forum Index -> Автоматизация Total Commander printer-friendly view
View previous topic :: View next topic  
Author Message
Flasher



Joined: 06 Nov 2009
Posts: 14229
Location: Москва

Post (Separately) Posted: Tue Oct 12, 2010 23:38    Post subject: Добавление текста до/после строк в выделенных файл-списках Reply with quote

Давно появилась задача по редактированию строк в файл-списках.
Вот что примерно хотелось бы видеть:

Для AutoIt: одно окно с восьмью полями:
Маска файлов [__]
_________________Вставка текста________________
Слева от строки__[__]___начинающейся с_______[__]*
Справа от строки_[__]___заканчивающейся на___[__]*
Над строкой_____[__]___начинающейся с_______[__]*
Под строкой._____[__]__заканчивающейся на____[__]*
* Если какие-то поля справа пустуют, а слева нет, то обрабатываются все строки по заданным условиям в левых полях.

Для VBS: 4 окна, которые вызываются с учётом заданных через пробел параметров.
1 - вызывает окно "Вставьте текст слева от строки"
2 - вызывает окно "Вставьте текст справа от строки"
3 - вызывает окно "Вставьте текст над строкой"
4 - вызывает окно "Вставьте текст под строкой"
Необходимо комбинировать(1 2 | 2 4 | 1 3 4 и т.д.).


Для обоих случаев:
- если поля "..над строкой" и "..под строкой" пустуют, то не должны создаваться пустые строки;
- исходные пустые строки в файлах не должны обрабатываться(можно добавить параметр на их удаление).

P.S. C vbs я и сам могу поковыряться, просто у меня это времени поболе займёт.
Back to top
View user's profile Send private message
Loopback



Joined: 07 Sep 2009
Posts: 1536

Post (Separately) Posted: Wed Oct 13, 2010 15:45    Post subject: Reply with quote

Честно говоря вообще не понял логики, как что должно работать. Например:

Слева от строки__[__]___начинающейся с_______[__]*
Справа от строки_[__]___заканчивающейся на___[__]*

Что представляет собой значение "Слева от строки"? Номер строки?
Или если это текст строки, зачем нужно "начинающейся с"?

Да и вообще, как тогда понимать "над" и "под" строкой? В этом случае, получается, строку надо брать целиком.
Back to top
View user's profile Send private message
Flasher



Joined: 06 Nov 2009
Posts: 14229
Location: Москва

Post (Separately) Posted: Wed Oct 13, 2010 15:51    Post subject: Reply with quote

Loopback wrote:
Что представляет собой значение "Слева от строки"? Номер строки?
Вставка текста слева от любой строки в списке.
Пример:
1 строка: 2222357
2 строка: 4543638

Добавить слева:
блабла
блаблабла
блабла

Результат:
блабла
блаблабла
блабла2222357
блабла
блаблабла
блабла4543638

Loopback wrote:
Или если это текст строки, зачем нужно "начинающейся с"?
Это нужно в случае, если требуется фильтр строк. Т.е. выборочное добавление.
Loopback wrote:
Да и вообще, как тогда понимать "над" и "под" строкой?
Над строкой - на предыдущей строке(ах), под строкой - начиная со следующей строки.
результат вставки над строкой:
блабла
блаблабла
блабла
2222357
блабла
блаблабла
блабла
4543638
Back to top
View user's profile Send private message
Loopback



Joined: 07 Sep 2009
Posts: 1536

Post (Separately) Posted: Wed Oct 13, 2010 16:41    Post subject: Reply with quote

Flasher wrote:
Вставка текста слева от любой строки в списке.

Эээ. Если любой, то нафиг тут тогда поле ввода? Наверно достаточно фильтра? Т.е.

Слева от строки, начинающейся с_______[__]*

Если поле пустое - любая строка.

Кстати, режимы "над" и "под" ничем, по-сути, отличаются от первых двух только добавлением перевода строки. Если в поле ввода вставить дополнительный перенос до или после текста - получим тот же результат. Нужно ли плодить сущности в виде лишних полей?
Back to top
View user's profile Send private message
Flasher



Joined: 06 Nov 2009
Posts: 14229
Location: Москва

Post (Separately) Posted: Wed Oct 13, 2010 16:51    Post subject: Reply with quote

Loopback wrote:
Если любой, то нафиг тут тогда поле ввода?
Что значит "нафиг"? Это самое важное. Текст туда вообще-то должен вводится, который вставлять надо. Smile

Loopback wrote:
Наверно достаточно фильтра? Т.е.
Я же поясняю, что фильтр нужен для выбора тех строк, около которых будет вводится текст, вставленный в поле слева.
Loopback wrote:
Если поле пустое - любая строка.
Это условие я написал в первом посте, логично. Smile

Loopback wrote:
Нужно ли плодить сущности в виде лишних полей?
Так тут комбинация важна. Вставка у одних строк с фильтром будет спереди/сзади, у других над/под. Плюс ко всему - это удобней, чем приписывать переносы или, допустим, ставить флаги с длинными названиями, которые тоже будут место занимать.
Back to top
View user's profile Send private message
Loopback



Joined: 07 Sep 2009
Posts: 1536

Post (Separately) Posted: Wed Oct 13, 2010 17:26    Post subject: Reply with quote

Flasher wrote:
Текст туда вообще-то должен вводится, который вставлять надо.

Ну ты и пишешь Rolling Eyes Как это можно было понять из текста? В жизни бы не догадался. Я полагал "Вставка текста" - это текст, на который меняем, а всё остальное - условия, в этом случае первые пункты за условие ну никак не катили.

Flasher wrote:
Я же поясняю, что фильтр нужен

С фильтром как раз всё было понятно. Впрочем, вышесказанное всё расставило на места.

Ок, посмотрю вечером.
Back to top
View user's profile Send private message
Flasher



Joined: 06 Nov 2009
Posts: 14229
Location: Москва

Post (Separately) Posted: Wed Oct 13, 2010 17:38    Post subject: Reply with quote

Loopback wrote:
Ну ты и пишешь Rolling Eyes Как это можно было понять из текста?
Смотря из какого. Wink Там написано "Вставка текста", а далее ветви(слева.., справа.., над.., под..). Что'ж ещё в поля-то вводить? Smile
Loopback wrote:
Я полагал "Вставка текста" - это текст, на который меняем
Ну про "менять" я нигде не писал, лишь "вставлять". Ты имел в виду, что текст один единственный? Smile Если да, то для него бы я отобразил отдельное поле, которое и могло бы привести в замешательство, а так там его нет. Smile
Loopback wrote:
Ок, посмотрю вечером.
Спасибо!
Back to top
View user's profile Send private message
Loopback



Joined: 07 Sep 2009
Posts: 1536

Post (Separately) Posted: Thu Oct 14, 2010 10:04    Post subject: Reply with quote

Flasher
Вечером не вышло.

Кстати, как обрабатывать ситуацию, когда заполнены, скажем, первое и третье поле с текстом? Допустим, скрипт обработал первое поле, добавил слева текст. Далее есть еще условие добавления перед. Добавляем перед строкой с уже добавленным слева текстом? Но если при этом задано условие выбора строки - как быть? После добавления текста, по-сути, начало строки меняется.

Чтобы всё было попрозрачнее, предлагаю сделать так: все условия выбора строки делать только по исходной строке. Последовательность обработки текста - сначала присоединять слева(справа), а потом сверху(снизу).
Back to top
View user's profile Send private message
Flasher



Joined: 06 Nov 2009
Posts: 14229
Location: Москва

Post (Separately) Posted: Thu Oct 14, 2010 11:27    Post subject: Reply with quote

Loopback wrote:
Но если при этом задано условие выбора строки - как быть? После добавления текста, по-сути, начало строки меняется.
Я даже удивился, почему ты вчера сразу об этом не спросил.) Если задано условие выбора, то обработка идёт вкупе с остальными строками. Совпадения могут быть при условии, что юзер просто не знаком с синтаксисом списков, что было бы ОЧЕНЬ странно. Если условие выбора на 1/3 или 2/4 строки не задано одновременно, то в порядке приоритета обрабатываться должны только 1,2 строки(слева, справа), а потом по окончанию 3/4(над, под).

Loopback wrote:
все условия выбора строки делать только по исходной строке.
Секундочку. По какой исходной? Там всего 4 поля с добавляющимся текстом для каждого отдельного случая. Никакого общего текста для всех 4-х вариантов быть не должно.
Back to top
View user's profile Send private message
Loopback



Joined: 07 Sep 2009
Posts: 1536

Post (Separately) Posted: Thu Oct 14, 2010 13:17    Post subject: Reply with quote

Flasher wrote:
Если условие выбора на 1/3 или 2/4 строки не задано одновременно

Наверно, имелось в виду все-таки "задано одновременно"?


Flasher wrote:
По какой исходной?

Ну вот прочитана строка из файла - все фильтры сравниваются с ней, назависимо от того, добавило ли предыдущее условие к ней текст.
Back to top
View user's profile Send private message
Flasher



Joined: 06 Nov 2009
Posts: 14229
Location: Москва

Post (Separately) Posted: Thu Oct 14, 2010 13:33    Post subject: Reply with quote

Loopback wrote:
Наверно, имелось в виду все-таки "задано одновременно"?
Нет-нет-нет, именно с частицей "не", т.е. если правые поля 1/3, 2/4 пустуют. Ведь в таком случае будут обрабатываться все строки без фильтра кроме пустых, конечно.
Loopback wrote:
Ну вот прочитана строка из файла - все фильтры сравниваются с ней, назависимо от того, добавило ли предыдущее условие к ней текст.
Ааа, в этом смысле. Т.е. не каждый раз прочитывать, а сразу для всех 4-х случаев? Тогда, конечно, ты прав. Только в этом случае я бы хотел добавить флаги с приоритетами. Т.е., если условия справа одинаковые, то приоритет позволит добавлять, например, сперва по "над" перед "слева" или "под" перед "справа".
Back to top
View user's profile Send private message
Loopback



Joined: 07 Sep 2009
Posts: 1536

Post (Separately) Posted: Thu Oct 14, 2010 21:06    Post subject: Reply with quote

Так, что-то туго дело идет... Confused

Вроде что-то изобразил, но тут сейчас обратил внимание - "файл-списках". Имеется в виду тот файл-список, который создает тотал по %L? А то я как предыдущий сделал, т.е. с поиском и обработкой файлов.
Back to top
View user's profile Send private message
Flasher



Joined: 06 Nov 2009
Posts: 14229
Location: Москва

Post (Separately) Posted: Thu Oct 14, 2010 21:20    Post subject: Reply with quote

Loopback wrote:
Так, что-то туго дело идет.
Ничего, уж ради такой важной задачи можно и потерпеть. Wink
Loopback wrote:
Имеется в виду тот файл-список, который создает тотал по %L?
В названии темы написано "в выделенных файл-списках". В выделенных папках тоже было бы не плохо файлы по маске редактировать. Списки это или любые другие некодированные файлы(ini, htm(l) , xml, php, txt, lst, cfg, bar, lng, mnu и т.д.)- не суть важно, главное, чтобы алгоритм работал исходя из условий задачи.
Back to top
View user's profile Send private message
Loopback



Joined: 07 Sep 2009
Posts: 1536

Post (Separately) Posted: Thu Oct 14, 2010 21:44    Post subject: Reply with quote

Ладно, вот что получилось. Сделал как понял, если что не так - будем поправлять в рабочем порядке.

Code:

;; Параметры: %L

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

Global $aList  = _TCHLoadFileList($CmdLine[1])
Global $gBackups = False, $gCaseSence = 0
Global Const $GUI_CHECKED = 1
Global $gRemoveEmpty = False
Global $gIniFile = StringLeft(@ScriptFullPath, StringInStr(@ScriptFullPath, ".", 0, -1)) & "ini"

$hGUI = GUICreate("Вставка текста", 549, 570, -1, -1)
$edTextLeft = GUICtrlCreateEdit("", 8, 96, 529, 73)
$btnOK = GUICtrlCreateButton("OK", 384, 528, 75, 25)
$btnCancel = GUICtrlCreateButton("Отмена", 464, 528, 75, 25)
GUICtrlCreateLabel("начинающейся на", 198, 70, 94, 17, 0x2)
$cbCaseSence = GUICtrlCreateCheckbox("Учитывать регистр", 8, 520, 137, 17)
$edMask = GUICtrlCreateInput("*.*", 8, 24, 265, 21)
GUICtrlCreateLabel("Маска файлов", 8, 6, 78, 17)
$edTextRight = GUICtrlCreateEdit("", 8, 208, 529, 73)
$edTextBefore = GUICtrlCreateEdit("", 8, 320, 529, 73)
$edTextAfter = GUICtrlCreateEdit("", 8, 432, 529, 73)
GUICtrlCreateLabel("заканчивающейся на", 176, 182, 113, 17, 0x2)
GUICtrlCreateLabel("начинающейся на", 196, 294, 95, 17, 0x2)
GUICtrlCreateLabel("заканчивающейся на", 176, 406, 113, 17, 0x2)
$ibFilterLeft = GUICtrlCreateInput("", 296, 66, 241, 21)
$ibFilterRight = GUICtrlCreateInput("", 296, 178, 241, 21)
$ibFilterBefore = GUICtrlCreateInput("", 296, 290, 241, 21)
$ibFilterAfter = GUICtrlCreateInput("", 296, 402, 241, 21)
GUICtrlCreateLabel("", 8, 56, 528, 2, 0x10)
GUIStartGroup()
$Radio1 = GUICtrlCreateRadio("Добавить к строке слева", 8, 69, 153, 17)
GUICtrlSetState(-1, $GUI_CHECKED)
GUICtrlSetTip(-1, "Приоритет над п.3")
$Radio3 = GUICtrlCreateRadio("Добавить сверху строки", 8, 293, 153, 17)
GUICtrlSetTip(-1, "Приоритет над п.1")
GUIStartGroup()
$Radio2 = GUICtrlCreateRadio("Добавить к строке справа", 8, 181, 161, 17)
GUICtrlSetState(-1, $GUI_CHECKED)
GUICtrlSetTip(-1, "Приоритет над п.4")
$Radio4 = GUICtrlCreateRadio("Добавить снизу строки", 8, 405, 153, 17)
GUICtrlSetTip(-1, "Приоритет над п.2")
$cbBackups = GUICtrlCreateCheckbox("Создавать резервные копии", 160, 520, 193, 17)
$cbRemoveEmpty = GUICtrlCreateCheckbox("Удалять пустые строки", 8, 544, 150, 17)
$cbCloseDone = GUICtrlCreateCheckbox("Закрывать по завершению", 160, 544, 160, 17)
Global $AccelTable[1][2] = [["^{ENTER}", $btnOK]]
GUISetAccelerators($AccelTable)

GUISetState(@SW_SHOW)

GUICtrlSetState($cbCaseSence,   IniRead($gIniFile, "Settings", "CaseSenseSearch", 4))
GUICtrlSetState($cbBackups,     IniRead($gIniFile, "Settings", "MakeBackups", 4))
GUICtrlSetState($cbRemoveEmpty, IniRead($gIniFile, "Settings", "RemoveEmptyLines", 4))
GUICtrlSetState($cbCloseDone,   IniRead($gIniFile, "Settings", "CloseWhenDone", 1))


While 1
   $nMsg = GUIGetMsg()
   Switch $nMsg
      Case -3, $btnCancel
        Exit
      Case $btnOK
        $gMask = _MaskToRegexp(GUICtrlRead($edMask))
        $gBackups = BitAND(GUICtrlRead($cbBackups), $GUI_CHECKED)
        $gRemoveEmpty = BitAND(GUICtrlRead($cbRemoveEmpty), $GUI_CHECKED)
        If BitAND(GUICtrlRead($cbCaseSence), $GUI_CHECKED) Then $gCaseSence = 1
        WinSetState($hGUI, "", @SW_DISABLE)

        IniWrite($gIniFile, "Settings", "CaseSenseSearch",  GUICtrlRead($cbCaseSence))
        IniWrite($gIniFile, "Settings", "MakeBackups",      GUICtrlRead($cbBackups))
        IniWrite($gIniFile, "Settings", "RemoveEmptyLines", GUICtrlRead($cbRemoveEmpty))
        IniWrite($gIniFile, "Settings", "CloseWhenDone",    GUICtrlRead($cbCloseDone))

        For $i = 1 To $aList[0]
            If StringRight($aList[$i], 1) = "\" Then
                _DoFolder($aList[$i])
            Else
                _DoFile($aList[$i])
            EndIf
        Next
        MsgBox (0, "", "Завершено.", 0, $hGUI)
        If BitAND(GUICtrlRead($cbCloseDone), $GUI_CHECKED) Then Exit
        WinSetState($hGUI, "", @SW_ENABLE)
   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 _ProcessLines(ByRef $aSrcFile, ByRef $aTrgFile, $sText, $sFilter, $nMode)
    If $sText = "" Then Return
    For $i = 1 To $aSrcFile[0]
        Switch $nMode
            Case 0, 2
                If ($sFilter <> "") Then
                    $sLeft = StringLeft($aSrcFile[$i], StringLen($sFilter))
                    If $gCaseSence Then
                        If Not ($sLeft == $sFilter) Then ContinueLoop
                    Else
                        If $sLeft <> $sFilter Then ContinueLoop
                    EndIf
                EndIf
                If $nMode = 2 Then $aTrgFile[$i] = @CRLF & $aTrgFile[$i]
                $aTrgFile[$i] = $sText & $aTrgFile[$i]
            Case 1, 3
                If ($sFilter <> "") Then
                    $sRight = StringRight($aSrcFile[$i], StringLen($sFilter))
                    If $gCaseSence Then
                        If Not ($sRight == $sFilter) Then ContinueLoop
                    Else
                        If $sRight <> $sFilter Then ContinueLoop
                    EndIf
                EndIf
                If $nMode = 3 Then $aTrgFile[$i] = $aTrgFile[$i] & @CRLF
                $aTrgFile[$i] = $aTrgFile[$i] & $sText
        EndSwitch
    Next
EndFunc

Func _DoFile($sFile)
    If StringRegExp(StringLower($sFile), $gMask) = 0 Then Return
    Local $aSrcFile = _TCHLoadFileList($sFile)
    If $gRemoveEmpty And ($aSrcFile[0] > 0) Then
        Local $aTrgFile[$aSrcFile[0]+1] = [0]
        For $i = 1 To $aSrcFile[0]
            If $aSrcFile[$i] <> "" Then
                $aTrgFile[0] += 1
                $aTrgFile[$aTrgFile[0]] = $aSrcFile[$i]
            EndIf
        Next
        ReDim $aTrgFile[$aTrgFile[0] + 1]
        $aSrcFile = $aTrgFile
    Else
        Local $aTrgFile = $aSrcFile
    EndIf

    If BitAND(GUICtrlRead($Radio1), $GUI_CHECKED) Then
        _ProcessLines($aSrcFile, $aTrgFile, GUICtrlRead($edTextLeft), GUICtrlRead($ibFilterLeft), 0)
        _ProcessLines($aSrcFile, $aTrgFile, GUICtrlRead($edTextbefore), GUICtrlRead($ibFilterBefore), 2)
    Else
        _ProcessLines($aSrcFile, $aTrgFile, GUICtrlRead($edTextbefore), GUICtrlRead($ibFilterBefore), 2)
        _ProcessLines($aSrcFile, $aTrgFile, GUICtrlRead($edTextLeft), GUICtrlRead($ibFilterLeft), 0)
    EndIf

    If BitAND(GUICtrlRead($Radio3), $GUI_CHECKED) Then
        _ProcessLines($aSrcFile, $aTrgFile, GUICtrlRead($edTextRight), GUICtrlRead($ibFilterRight), 1)
        _ProcessLines($aSrcFile, $aTrgFile, GUICtrlRead($edTextAfter), GUICtrlRead($ibFilterAfter), 3)
    Else
        _ProcessLines($aSrcFile, $aTrgFile, GUICtrlRead($edTextAfter), GUICtrlRead($ibFilterAfter), 3)
        _ProcessLines($aSrcFile, $aTrgFile, GUICtrlRead($edTextRight), GUICtrlRead($ibFilterRight), 1)
    EndIf

    If $gBackups Then FileCopy($sFile, $sFile & ".bak", 1) ; бэкап
    Local $hFile = FileOpen($sFile, 2)
    For $i = 1 To $aTrgFile[0]
        FileWriteLine($hFile, $aTrgFile[$i])
    Next
    FileClose($hFile)
EndFunc

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

; fast list load function
Func _TCHLoadFileList($sFileName, $nIncBlock = 1000)
    Local $asList[$nIncBlock + 1] = [0]
    Local $hfList = FileOpen($sFileName, 0)
    Local $nCounter = 0
    While 1
        For $i = 1 To $nIncBlock
            $asList[$nCounter + $i] = FileReadLine($hfList)
            If @error Then
                ReDim $asList[UBound($asList) + $i - $nIncBlock - 1]
                ExitLoop(2)
            EndIf
        Next
        $nCounter += $nIncBlock
        ReDim $asList[UBound($asList)+$nIncBlock]
    Wend
    FileClose($hfList)
    $asList[0] = UBound($asList)-1
    Return $asList
EndFunc


Last edited by Loopback on Wed Oct 20, 2010 13:44; edited 3 times in total
Back to top
View user's profile Send private message
Flasher



Joined: 06 Nov 2009
Posts: 14229
Location: Москва

Post (Separately) Posted: Thu Oct 14, 2010 22:11    Post subject: Reply with quote

О, почти то, что надо! Smile
Пока не тестил, сразу что в глаза бросилось:
названия полей лучше не писать через запятую, иначе условия будут восприниматься как необходимые. Стоит текст до запятой сдвинуть до конца влево, а после вправо( и чтобы они отстояли на одинаковом расстоянии от полей с фильтром).
Слова "слева/справа" лучше поменять местами с "к строке". Так лучше по стилистике.
"Перед"/"после" - может восприниматься как слева/справа, так и над/под. Я бы заменил на "сверху"/"снизу" строки. (У себя, естественно, уже поменял.)
Само окно можно поуже сделать на расстояние от слова "копии" до кнопки ОК + от слова "регистр" до флага.
Хорошо было бы добавить птицу "Закрывать после выполнения".
Поля фильтра желательно сделать равной длины.
Про флаги с приоритетами, надеюсь, не забыл? Wink
Об остальном чуть позже.

Добавлено: что-то не хочет скрипт работать, что с фильтром, что без. Sad
Пробовал с одним файлом под курсором, с выделенным файлом, с выделенными папками.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Total Commander Forum Index -> Автоматизация Total Commander All times are GMT + 4 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group