|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » VBS/WSH/JS - [решено] [VBS] Сортировка текстовых строк с учётом директорий |
|
VBS/WSH/JS - [решено] [VBS] Сортировка текстовых строк с учётом директорий
|
Старожил Сообщения: 267 |
Есть текстовые строки (именно строки, а не пути к существующим файлам)
\F1\1.txt \F111\2.txt \f11.txt \f33.txt \f22.txt \F0\3.txt \F0\1.txt \F0\2\2.txt \F1\ \F0\ \F0\2\ \F111\ \F0\ \F0\1.txt \F0\2\ \F0\2\2.txt \F0\3.txt \f11.txt \F111\ \F111\2.txt \F1\ \F1\1.txt \f22.txt \f33.txt \f11.txt \f22.txt \f33.txt \F0\ \F0\1.txt \F0\3.txt \F0\2\ \F0\2\2.txt \F1\ \F1\1.txt \F111\ \F111\2.txt \F0\ \F0\2\ \F0\2\2.txt \F0\1.txt \F0\3.txt \F1\ \F1\1.txt \F111\ \F111\2.txt \f11.txt \f22.txt \f33.txt Как это сделать? есть решение или алгоритм? это должна быть рекурсивная функция? через split("\") ? |
|
Отправлено: 14:03, 05-01-2020 |
Старожил Сообщения: 267
|
Профиль | Отправить PM | Цитировать Цитата megaloman:
Цитата megaloman:
строки берутся из FSO, который загоняет их в коллекцию простым прогоном по всему дереву (Dir не понимает юникод в именах) далее две коллекции с деревьями объединяются, отрезается начальный каталог, убираются дубли, остаётся коллекция с уникальными строками из обеих папок (в первом сообщении первый код под фразой "Есть текстовые строки:") Цитата megaloman:
учитывать разный регистр необходимо, потому что в одной папке может быть \Folder\File1.txt , а в другой \FOLDER\file1.txt , в Windows это один и тот же путь, а при обработке строка "\Folder\File1.txt" не равна "\FOLDER\file1.txt", поэтому и сортируем через lcase, а результат выдаём в оригинальном регистре да и к тому же этот переключатель регистра легко можно настроить. на самом деле их два. 1. сортировка с учетом регистра (или без учета) и 2. выдача результата в оригинальном регистре или в нижнем/верхнем это всё кому как удобнее и на метод пузырька не влияет в данном случае, найти удобный/быстрый метод сортировки это тоже не проблема, методов сортировки много, вплоть до внешних библиотек, я всего лишь уточнил, что метод сортировки необходимо изменить на любой другой, а на какой именно уже не так важно вообще, во всей этой теме гениальные строки с заменой слеша на Chr(0) и подстановка перед файлом Chr(1), что позволяет сортировать строки любым обычным способом, который подходит для сортировки текста и делать любую обвязку кому как удобнее, это не предмет спора вообще |
|||
Последний раз редактировалось shadowbat, 08-01-2020 в 23:28. Отправлено: 22:58, 08-01-2020 | #21 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Ветеран Сообщения: 2728
|
Профиль | Отправить PM | Цитировать shadowbat, Подозреваю, сортировка не нужна вовсе. По голому имени нельзя узнать, файлы или изменены или равны. Надо четкая постановка. Возможно, есть готовый софт для этого. И зачем при сравнении наличия файлов надо перечислять имена директорий? Почему не ограничиться только полными именами файлов?
|
------- Отправлено: 23:29, 08-01-2020 | #22 |
Старожил Сообщения: 267
|
Профиль | Отправить PM | Цитировать Цитата megaloman:
Цитата megaloman:
вопрос был конкретно по сортировке директорий, представленных в виде строк. несколько разных готовых .exe софтов для сравнения двух папок, конечно, тоже существует на просторах интернета. часто подаётся под соусом "синхронизация", что, по мне, является совершенно отдельной задачей. например существует сравнение текстовых и бинарных файлов, но не существует синхронизации файлов, потому что впихивать содержимое одного файла в другой никому не приходит в голову Цитата megaloman:
у каких то людей/программ только файлы, у иных и файлы и папки, а может у кого-то список только папок. сортировка только файлов без учёта папок является полумерой это как сортировать строки текста без учёта спец символов !@№;%:?, не во всех же строках они имеются, зачем их учитывать при сортировке? |
|||
Последний раз редактировалось shadowbat, 08-01-2020 в 23:53. Отправлено: 23:35, 08-01-2020 | #23 |
Ветеран Сообщения: 27449
|
Профиль | Отправить PM | Цитировать shadowbat, ну, вот, я как-то вполне обхожусь Far Manager'ом с парой-тройкой плагинов плюс внешним CloneSpy для покрытия всего спектра своих задач по полуавтоматическому сравнению каталогов и файлов.
Для сортировки строк, занимающей длительное время, есть смысл применять либо System.Collections.ArrayList/System.Collections.Sortedlist из .Net (возможно, потребуется однократно зарегистрировать библиотеку), либо базу данных в памяти. |
Отправлено: 00:43, 09-01-2020 | #24 |
Старожил Сообщения: 352
|
Профиль | Отправить PM | Цитировать Цитата shadowbat:
|
|
Отправлено: 00:47, 09-01-2020 | #25 |
Старожил Сообщения: 267
|
Профиль | Отправить PM | Цитировать К сожалению при выгрузке на лист есть две проблемы:
1. Chr(0) не обрабатывается, и обрезается, таким образом вместо Chr(0) Chr(1) необходимо использовать например Chr(1) Chr(2) 2. Родная сортировка Exl не учитывает символы Chr(0-31), таким образом Chr(0) и Chr(1) нужно заменить на любой другой (невстречающийся) набор печатных символов с номером >31 согласно таблице ascii, например &0& и &1& , в идеале нужно использовать любые "неправильные" символы \ / : * ? " < > | |
Последний раз редактировалось shadowbat, 22-01-2020 в 10:57. Отправлено: 03:40, 19-01-2020 | #26 |
Ветеран Сообщения: 2728
|
Профиль | Отправить PM | Цитировать shadowbat, Пробуйте, интересно, быстрее сортировка?
|
------- Отправлено: 19:41, 20-01-2020 | #27 |
Старожил Сообщения: 267
|
Профиль | Отправить PM | Цитировать Цитата megaloman:
2. в цикле For i = N1 + 1 To N2 идёт накопление и Exl ненадолго подвисает на примерно i=16000-25000 (возможно точное число зависит от конфигурации машины), если добавить строку If i Mod 1000 = 0 Then Debug.Print i , то видно как скорость печати постепенно уменьшается до (Не отвечает). при этом в диспетчере задач видно, что Exl продолжает работать и в конечном итоге отвисает. 65000 строк сортирует за 2-3 минуты, что конечно быстрее прошлого значения 3. при сохранении 65000 длинных строк со средней длиной 50 была ошибка. на строке .Write SS при работе с 65000 строками выдал "Ошибка: Run-time error '5': Invalid procedure call or argument", если строк меньше, то сохраняет нормально. если 65000 коротких (!) строк, то тоже сохраняет нормально. со средней длиной строк 30 сохранил нормально, если средняя длина строк 50, то ошибку выдает. может быть влияет не длина строк, а какие-то символы в пути, пока неизвестно скопировал код из архива: я200120.xlsm.rar
Sub rrr() FileIn = "Z:\Box_In\filein.txt" FileOut = "Z:\Box_Out\fileoutxls.txt" Rang1 = "C2" R1 = Range(Rang1).Row C1 = Range(Rang1).Column Set FSO = CreateObject("Scripting.FileSystemObject") On Error Resume Next With FSO.OpenTextFile(FileIn, 1, False) If Err.Number <> 0 Then MsgBox "File " + FileIn + vbCrLf + Err.Description + "(" + CStr(Err.Number) + ")" WScript.Quit 2 End If On Error GoTo 0 Alls = Split(.ReadAll, vbCrLf) .Close End With N = LBound(Alls) - 1 NN = -1 For Each s In Alls s = Trim(s) If Len(s) <> 0 Then N = N + 1 NN = NN + 1 ii = InStrRev(s, "\") s = Mid(s, 1, ii - 1) + Replace(s, "\", "**", ii) s = Replace(s, "\", "*") Alls(N) = s End If Next Set RR = Range(Cells(R1, C1), Cells(R1 + NN, C1)) RR.Value = WorksheetFunction.Transpose(Alls) Erase Alls ActiveWorkbook.ActiveSheet.Sort.SortFields.Clear ActiveWorkbook.ActiveSheet.Sort.SortFields.Add Key:=Range(Rang1), _ SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _ xlSortTextAsNumbers With ActiveWorkbook.Worksheets("Лист3").Sort .SetRange RR .Header = xlGuess .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With Alls = RR N1 = LBound(Alls, 1) N2 = UBound(Alls, 1) s = Alls(N1, 1) s = Replace(Replace(s, "**", "\"), "*", "\") Alls(N1, 1) = s SS = s For i = N1 + 1 To N2 s = Alls(i, 1) s = Replace(Replace(s, "**", "\"), "*", "\") Alls(i, 1) = s SS = SS + vbCrLf + s Next RR.Value = Alls With FSO.CreateTextFile(FileOut, True) .Write SS .Close End With MsgBox "Done" End Sub |
|
Последний раз редактировалось shadowbat, 22-01-2020 в 10:59. Отправлено: 10:26, 22-01-2020 | #28 |
Ветеран Сообщения: 2728
|
Профиль | Отправить PM | Цитировать shadowbat, Происследовал затраты времени на исполнение этапов макроса. Выяснил, что накапливать очень длинную строку - это катастрофа по времени.
Вот изменённый макрос
Sub rrr() FileIn = "Z:\Box_In\fileinRND.txt" FileOut = "Z:\Box_Out\fileoutRND.txt" Rang1 = "C2" 'C какой ячейки нечинаются данные Rang1 = "D1" TTT = Timer R1 = Range(Rang1).Row C1 = Range(Rang1).Column With CreateObject("VBScript.RegExp") .Pattern = "[0-9]" .IgnoreCase = True .Global = True NameCol = .Replace(Rang1, "") End With Columns(NameCol).ClearContents Set FSO = CreateObject("Scripting.FileSystemObject") On Error Resume Next With FSO.OpenTextFile(FileIn, 1, False) If Err.Number <> 0 Then MsgBox "File " + FileIn + vbCrLf + Err.Description + "(" + CStr(Err.Number) + ")" WScript.Quit 2 End If On Error GoTo 0 Alls = Split(.ReadAll, vbCrLf) .Close End With On Error GoTo 0 N = LBound(Alls) - 1 NN = -1 For Each S In Alls S = Trim(S) If Len(S) <> 0 Then N = N + 1 NN = NN + 1 ii = InStrRev(S, "\") S = Mid(S, 1, ii - 1) + Replace(S, "\", Chr(42) + Chr(42), ii) S = Replace(S, "\", Chr(42)) Alls(N) = S End If Next ReDim Alls2(1 To NN + 1, 1 To 1) For i = 1 To NN + 1 Alls2(i, 1) = Alls(i - 1) Next Erase Alls Set RR = Range(Cells(R1, C1), Cells(R1 + NN, C1)) RR.Value = Alls2 Erase Alls2 'MsgBox "Посадили файл в таблицу (sec) " + CStr(Timer - TTT) TTT1 = Timer ActiveWorkbook.ActiveSheet.Sort.SortFields.Clear ActiveWorkbook.ActiveSheet.Sort.SortFields.Add Key:=Range(Rang1), _ SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _ xlSortTextAsNumbers With ActiveWorkbook.ActiveSheet.Sort .SetRange RR .Header = xlGuess .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With 'MsgBox "Отсортировали (sec) " + CStr(Timer - TTT1) TTT1 = Timer Alls = RR 'MsgBox "Забрали отсорт в массив (sec) " + CStr(Timer - TTT1) TTT1 = Timer N1 = LBound(Alls, 1) N2 = UBound(Alls, 1) With FSO.CreateTextFile(FileOut, True) For i = N1 To N2 Alls(i, 1) = Replace(Replace(Alls(i, 1), Chr(42) + Chr(42), "\"), Chr(42), "\") If i < N2 Then .WriteLine Alls(i, 1) Else .Write Alls(i, 1) End If Next .Close End With RR.Value = Alls 'MsgBox "Done (sec) " + CStr(Timer - TTT1) + " (" + CStr(Timer - TTT) + ")" MsgBox "Done (sec) " + CStr(Timer - TTT) End Sub Sub GenOut() FileOut = "Z:\Box_In\fileinRND.txt" NRepeat = 2000 TTT = Timer Dim Sim(61) S = "" i = 0 For j = 1 To 3 If j = 1 Then k1 = 48: k2 = 57 If j = 2 Then k1 = 65: k2 = 90 If j = 3 Then k1 = 97: k2 = 122 For k = k1 To k2 Sim(i) = Chr(k) S = S + Sim(i) '+ vbCrLf i = i + 1 Next Next Set FSO = CreateObject("Scripting.FileSystemObject") With FSO.CreateTextFile(FileOut, True) For i = 1 To NRepeat '''''''''' MsgBox sRND(1, 5, Sim) ' 1,5 - диапазон кол-ва симв в сформир строке; Sim - масс символов If (i - 1) Mod 100 = 0 Then sTotal = "\" + sRND(6, 8, Sim) + ".txt" Else sTotal = "" S1 = sRND(3, 5, Sim) S2 = sRND(3, 5, Sim) S3 = sRND(3, 5, Sim) T1 = sRND(2, 5, Sim) + ".txt" T2 = sRND(2, 5, Sim) + ".txt" T3 = sRND(2, 5, Sim) + ".txt" sTotal = sTotal + vbCrLf + "\" + S1 + "\" + S2 + "\" + S3 + "\" + T1 sTotal = sTotal + vbCrLf + "\" + S1 + "\" + S2 + "\" + S3 + "\" + T2 sTotal = sTotal + vbCrLf + "\" + S1 + "\" + S2 + "\" + S3 + "\" + T3 sTotal = sTotal + vbCrLf + "\" + S2 + "\" + S3 + "\" + S1 + "\" + T1 sTotal = sTotal + vbCrLf + "\" + S2 + "\" + S3 + "\" + S1 + "\" + T2 sTotal = sTotal + vbCrLf + "\" + S2 + "\" + S3 + "\" + S1 + "\" + T3 sTotal = sTotal + vbCrLf + "\" + S3 + "\" + S1 + "\" + S2 + "\" + T1 sTotal = sTotal + vbCrLf + "\" + S3 + "\" + S1 + "\" + S2 + "\" + T2 sTotal = sTotal + vbCrLf + "\" + S3 + "\" + S1 + "\" + S2 + "\" + T3 sTotal = sTotal + vbCrLf + "\" + S1 + "\" + S2 + "\" + S3 + "\" sTotal = sTotal + vbCrLf + "\" + S2 + "\" + S3 + "\" + S1 + "\" sTotal = sTotal + vbCrLf + "\" + S3 + "\" + S1 + "\" + S2 + "\" sTotal = sTotal + vbCrLf + "\" + S1 + "\" + S2 + "\" + T1 sTotal = sTotal + vbCrLf + "\" + S1 + "\" + S2 + "\" + T2 sTotal = sTotal + vbCrLf + "\" + S1 + "\" + S2 + "\" + T3 sTotal = sTotal + vbCrLf + "\" + S2 + "\" + S3 + "\" + T1 sTotal = sTotal + vbCrLf + "\" + S2 + "\" + S3 + "\" + T2 sTotal = sTotal + vbCrLf + "\" + S2 + "\" + S3 + "\" + T3 sTotal = sTotal + vbCrLf + "\" + S3 + "\" + S1 + "\" + T1 sTotal = sTotal + vbCrLf + "\" + S3 + "\" + S1 + "\" + T2 sTotal = sTotal + vbCrLf + "\" + S3 + "\" + S1 + "\" + T3 sTotal = sTotal + vbCrLf + "\" + S1 + "\" + S2 + "\" sTotal = sTotal + vbCrLf + "\" + S2 + "\" + S3 + "\" sTotal = sTotal + vbCrLf + "\" + S3 + "\" + S1 + "\" sTotal = sTotal + vbCrLf + "\" + S1 + "\" + T1 sTotal = sTotal + vbCrLf + "\" + S1 + "\" + T2 sTotal = sTotal + vbCrLf + "\" + S1 + "\" + T3 sTotal = sTotal + vbCrLf + "\" + S2 + "\" + T1 sTotal = sTotal + vbCrLf + "\" + S2 + "\" + T2 sTotal = sTotal + vbCrLf + "\" + S2 + "\" + T3 sTotal = sTotal + vbCrLf + "\" + S3 + "\" + T1 sTotal = sTotal + vbCrLf + "\" + S3 + "\" + T2 sTotal = sTotal + vbCrLf + "\" + S3 + "\" + T3 sTotal = sTotal + vbCrLf + "\" + S1 + "\" sTotal = sTotal + vbCrLf + "\" + S2 + "\" sTotal = sTotal + vbCrLf + "\" + S3 + "\" .WriteLine sTotal Next .Close End With MsgBox "Done (sec) " + CStr(Timer - TTT) End Sub Function nRND(min1, max1) nRND = Int((max1 - min1 + 1) * Rnd + min1) End Function Function sRND(min1, max1, SSS) nSim = UBound(SSS) sRND = "" For j = 1 To nRND(min1, max1) sRND = sRND + SSS(nRND(0, nSim)) Next End Function Если заархивируете и отдадите свой файл - поизмываюсь и над ним. |
------- Последний раз редактировалось megaloman, 22-01-2020 в 23:17. Причина: Исправление ошибки Отправлено: 21:12, 22-01-2020 | #29 |
Ветеран Сообщения: 27449
|
Профиль | Отправить PM | Цитировать Цитата megaloman:
|
|
Отправлено: 21:42, 22-01-2020 | #30 |
![]() |
Участник сейчас на форуме |
![]() |
Участник вне форума |
![]() |
Автор темы |
![]() |
Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Любой язык - [решено] Сравнение 2-х текстовых файлов и удаление дубликатов строк в 1-м файле. | Uragan66 | Скриптовые языки администрирования Windows | 2 | 26-05-2019 16:14 | |
Самостоятельно меняется первый символ строк в текстовых файлах (и другие проблемы) | lesnoj | Лечение систем от вредоносных программ | 4 | 11-11-2015 08:42 | |
CMD/BAT - [решено] удаление части строк из всех текстовых файлов в папке | icq99999999 | Скриптовые языки администрирования Windows | 4 | 06-11-2013 07:19 | |
Java - Сортировка строк по первому слову в алфавитном порядке | pogo | Программирование и базы данных | 5 | 23-12-2011 08:05 | |
Сортировщик строк в текстовых файлах. | borison | Программное обеспечение Windows | 2 | 04-02-2007 10:22 |
|