Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Необходимо найти все строки которые начинаются с "download:"https:" и заканчиваются (http://forum.oszone.net/showthread.php?t=340489)

angel_lyucifer 12-05-2019 05:52 2871263

Необходимо найти все строки которые начинаются с "download:"https:" и заканчиваются
 
Здравствуйте, нужна ваша помощь.
Есть текстовый файл сгенерированный программой, вид содержимого файла:
Код:

{'title':'Эпизод 1', 'file':'[1080p]//de2.anilibria.tv/videos/ts/8374/0001-hd/playlist.m3u8,[720p]//de2.anilibria.tv/videos/ts/8374/0001/playlist.m3u8,[480p]//de2.anilibria.tv/videos/ts/8374/0001-sd/playlist.m3u8', download:"https://x.anilibria.tv/get/3BdXdlP0bs4wlKyjQcXZpA/1557795967/mp4/8374/0001.mp4?download=Hitoribocchi no Marumaru Seikatsu-1-sd.mp4", 'id': 's1'},
{'title':'Эпизод 2', 'file':'[1080p]//de2.anilibria.tv/videos/ts/8374/0002-hd/playlist.m3u8,[720p]//de2.anilibria.tv/videos/ts/8374/0002/playlist.m3u8,[480p]//de2.anilibria.tv/videos/ts/8374/0002-sd/playlist.m3u8', download:"https://x.anilibria.tv/get/ciP3toJ3rI3-x25Rqxxa0g/1557795967/mp4/8374/0002.mp4?download=Hitoribocchi no Marumaru Seikatsu-2-sd.mp4", 'id': 's2'},
{'title':'Эпизод 3', 'file':'[1080p]//de2.anilibria.tv/videos/ts/8374/0003-hd/playlist.m3u8,[720p]//de2.anilibria.tv/videos/ts/8374/0003/playlist.m3u8,[480p]//de2.anilibria.tv/videos/ts/8374/0003-sd/playlist.m3u8', download:"https://x.anilibria.tv/get/2xTCA5dY7tiA634RtlXrTw/1557795967/mp4/8374/0003.mp4?download=Hitoribocchi no Marumaru Seikatsu-3-sd.mp4", 'id': 's3'},
{'title':'Эпизод 4', 'file':'[1080p]//de2.anilibria.tv/videos/ts/8374/0004-hd/playlist.m3u8,[720p]//de2.anilibria.tv/videos/ts/8374/0004/playlist.m3u8,[480p]//de2.anilibria.tv/videos/ts/8374/0004-sd/playlist.m3u8', download:"https://x.anilibria.tv/get/Zgk0waIDnyzpgH4K3QM1hw/1557795967/mp4/8374/0004.mp4?download=Hitoribocchi no Marumaru Seikatsu-4-sd.mp4", 'id': 's4'},
{'title':'Эпизод 5', 'file':'[1080p]//de2.anilibria.tv/videos/ts/8374/0005-hd/playlist.m3u8,[720p]//de2.anilibria.tv/videos/ts/8374/0005/playlist.m3u8,[480p]//de2.anilibria.tv/videos/ts/8374/0005-sd/playlist.m3u8', Hitoribocchi no Marumaru Seikatsu-5-sd.mp4",
=Hitoribocchi no Marumaru Seikatsu-5-sd.mp4", 'id': 's5'}

Необходимо найти все строки которые начинаются с "download:"https:" и заканчиваются на ".mp4"," и удалить их.
Например чтобы были удалены только строки такого вида:
Код:

download:"https://x.anilibria.tv/get/z0k5b2jejzcDn4Ul35wXTg/1557778143/mp4/8330/0006.mp4?download=Midara na Ao-chan wa Benkyou ga Dekinai-6-sd.mp4",
Количество строк каждый раз разные....

megaloman 12-05-2019 15:16 2871316

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

FileIn = "Z:\Box_In\Исходный файл.txt"
S1 = "download:""https:"
S2 = ".mp4"","

With WScript.Arguments
    If .Count <> 0 Then FileIn = .Item(0)
End With

With CreateObject("Scripting.FileSystemObject")
    On Error Resume Next
    With .OpenTextFile(FileIn, 1)
        If Err.Number <> 0 Then
            MsgBox "Error open file " + vbCrLf + vbCrLf + FileIn + vbCrLf + vbCrLf + "Код ошибки " + CStr(Err.Number) + vbCrLf + Err.Description
            WScript.Quit 1
        End If
        InTxt = .ReadAll
        If Err.Number <> 0 Then
            MsgBox "Error read file " + vbCrLf + vbCrLf + FileIn + vbCrLf + vbCrLf + "Код ошибки " + CStr(Err.Number) + vbCrLf + Err.Description
            WScript.Quit 1
        End If
        .Close
        On Error GoTo 0
    End With
   
    Mas = Split(InTxt, vbCrLf)
    With .CreateTextFile(FileIn, True)
        For Each iMas In Mas
            If Not (InStr(1, iMas, S1) = 1 And (InStrRev(iMas, S2) + Len(S2) - 1) = Len(iMas)) Then
                .WriteLine iMas
            End If
        Next
        .Close
    End With
End With


Busla 12-05-2019 15:20 2871318

Код:

findstr /V /R "^download:\"https.*mp4\",$" text.txt

angel_lyucifer 13-05-2019 00:48 2871369

Цитата:

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

Скрипт запускается, но ничего не происходит.
А расширение вашего скрипта vbs?

Код:

FileIn = "Z:\Box_In\Исходный файл.txt"
S1 = "download:""https:"
S2 = ".mp4"","

With WScript.Arguments
    If .Count <> 0 Then FileIn = .Item(0)
End With

With CreateObject("Scripting.FileSystemObject")
    On Error Resume Next
    With .OpenTextFile(FileIn, 1)
        If Err.Number <> 0 Then
            MsgBox "Error open file " + vbCrLf + vbCrLf + FileIn + vbCrLf + vbCrLf + "Код ошибки " + CStr(Err.Number) + vbCrLf + Err.Description
            WScript.Quit 1
        End If
        InTxt = .ReadAll
        If Err.Number <> 0 Then
            MsgBox "Error read file " + vbCrLf + vbCrLf + FileIn + vbCrLf + vbCrLf + "Код ошибки " + CStr(Err.Number) + vbCrLf + Err.Description
            WScript.Quit 1
        End If
        .Close
        On Error GoTo 0
    End With
   
    Mas = Split(InTxt, vbCrLf)
    With .CreateTextFile(FileIn, True)
        For Each iMas In Mas
            If Not (InStr(1, iMas, S1) = 1 And (InStrRev(iMas, S2) + Len(S2) - 1) = Len(iMas)) Then
                .WriteLine iMas
            End If
        Next
        .Close
    End With
End With


megaloman 13-05-2019 01:25 2871372

angel_lyucifer, расширение vbs, заархивируйте и дайте образец Вашего файла, так можно сто лет гадать, в чем дело.

angel_lyucifer 13-05-2019 06:12 2871378

Вложений: 1
Цитата:

Цитата megaloman
заархивируйте и дайте образец Вашего файла, так можно сто лет гадать, в чем дело. »

Ок, вот.

YuS_2 13-05-2019 07:12 2871379

Цитата:

Цитата angel_lyucifer
Ок, вот. »

в этом файле всего одна строка, поэтому никаких строк:
Цитата:

Цитата angel_lyucifer
найти все строки которые начинаются с "download:"https:" и заканчиваются на ".mp4"," »

найдено не будет, т.к. они попросту не существуют в таком виде.

angel_lyucifer 14-05-2019 00:24 2871545

Цитата:

Цитата YuS_2
найдено не будет, т.к. они попросту не существуют в таком виде. »

Я вас понял, но всё же необходимо удалить все эти фрагменты в строке...

Iska 14-05-2019 01:05 2871549

Цитата:

Цитата angel_lyucifer
необходимо удалить все эти фрагменты в строке... »

Так это совсем другое дело, нежели озвученное ранее:
Цитата:

Цитата angel_lyucifer
Необходимо найти все строки которые начинаются с "download:"https:" и заканчиваются на ".mp4"," и удалить их. »

На PowerShell:
Код:

(Get-Content -Path 'C:\Мои проекты\0261\playlist.txt') -replace "download:`"https://.*?\.mp4`", " | Set-Content -Path 'C:\Мои проекты\0261\playlist2.txt'

angel_lyucifer 14-05-2019 05:34 2871550

Цитата:

Цитата Iska
На PowerShell: »

А можно ли на языке vbs?

megaloman 14-05-2019 07:28 2871557

А можно на языке vbs удалить все эти фрагменты
Код:

FileIn = "Z:\Box_In\playlist.txt"

RegExp = "download:""https:.*?\.mp4"", "

With WScript.Arguments
    If .Count <> 0 Then FileIn = .Item(0)
End With

With CreateObject("Scripting.FileSystemObject")
    On Error Resume Next
    With .OpenTextFile(FileIn, 1)
        If Err.Number <> 0 Then
            MsgBox "Error open file " + vbCrLf + vbCrLf + FileIn + vbCrLf + vbCrLf + "Код ошибки " + CStr(Err.Number) + vbCrLf + Err.Description
            WScript.Quit 1
        End If
        InTxt = .ReadAll
        If Err.Number <> 0 Then
            MsgBox "Error read file " + vbCrLf + vbCrLf + FileIn + vbCrLf + vbCrLf + "Код ошибки " + CStr(Err.Number) + vbCrLf + Err.Description
            WScript.Quit 1
        End If
        .Close
        On Error GoTo 0
    End With
           
    With CreateObject("VBScript.RegExp")
        .Pattern = RegExp
        .IgnoreCase = True
        .MultiLine = True
        .Global = True
        Result = .Replace(InTxt, "")
    End With
   
    With .CreateTextFile(FileIn, True)
        .Write Result
        .Close
    End With
   
End With
MsgBox "Done!"


YuS_2 14-05-2019 08:01 2871561

Цитата:

Цитата angel_lyucifer
А можно ли на языке vbs? »

пора переходить уже... ибо:
Цитата:

Цитата angel_lyucifer
Век живи, век учись! =) »

:wink:

angel_lyucifer 14-05-2019 11:49 2871593

Цитата:

Цитата megaloman
А можно на языке vbs удалить все эти фрагменты »

Спасибо вам большое....

Iska 14-05-2019 17:42 2871686

megaloman, несколько замечаний по коду:
  • .MultiLine в данном случае не нужен;
  • .Replace() следует выполнять только после проверки совпадения шаблона по .Test();
  • то же самое касается и пересоздания файла, дабы не переписывать одно и то же, т.е. и Replace(), и .CreateTextFile() должны быть внутри условия If .Test(…) Then … End If (на PowerShell, кстати, мне тоже следовало бы так делать).

Busla 14-05-2019 21:09 2871721

Цитата:

Цитата Iska
.Replace() следует выполнять только после проверки совпадения шаблона по .Test() »

нет

Цитата:

Цитата Iska
на PowerShell, кстати, мне тоже следовало бы так делать »

на PowerShell не надо пытаться писать как на (Visual)Basic

megaloman 14-05-2019 22:20 2871728

Цитата:

Цитата Iska
.Replace() следует выполнять только после проверки совпадения шаблона по .Test(); »

ИМХО, не так категорично. Однако, если помнить о том, что это
Цитата:

Цитата Iska
касается и пересоздания файла, дабы не переписывать одно и то же, »

то это было бы полезным.
Код:

.................
    With CreateObject("VBScript.RegExp")
        .Pattern = RegExp
        .IgnoreCase = True
        .Global = True
        If Not .Test(InTxt) Then
            MsgBox "no substrings to replace. Reg expression:" + vbCrLf + vbCrLf + """" + RegExp + """"
            WScript.Quit 1
        End If
        Result = .Replace(InTxt, "")
    End With
.................


Iska 15-05-2019 19:30 2871887

Цитата:

Цитата Busla
нет »

Да.

Цитата:

Цитата Busla
на PowerShell не надо пытаться писать как на (Visual)Basic »

Как токмо PowerShell превратится из процедурного языка в какой-нибудь функциональный — так сразу и начну не пытаться писать.

Цитата:

Цитата megaloman
ИМХО, не так категорично. »

Если для последующей обработки критичны дата/время файла, или же сам файл имеет объём, исчисляемый в сотнях мегабайт — то категорично. Лучше зараз привыкать.

Busla 15-05-2019 21:01 2871912

Цитата:

Цитата Iska
или же сам файл имеет объём, исчисляемый в сотнях мегабайт — то категорично. »

а если гигабайт?
Цитата:

Цитата Iska
Лучше зараз привыкать »

не надеяться на достаточный объём памяти, а работать построчно
тогда и вопрос перезаписи снимется

Цитата:

Цитата Iska
Как токмо »

не кривяйтесь

Цитата:

Цитата Iska
PowerShell превратится из процедурного языка в какой-нибудь функциональный »

аргументируйте: каким местом PowerShell нефункциональный? и почему он процедурный?

Iska 15-05-2019 21:51 2871925

Цитата:

Цитата Busla
а если гигабайт? »

То ещё категоричнее ;).

Цитата:

Цитата Busla
не надеяться на достаточный объём памяти, а работать построчно»

Это правильный подход.

Цитата:

Цитата Busla
тогда и вопрос перезаписи снимется »

Вопрос останется. Зачем переписывать много…байтный файл, в котором ничего не изменилось?

Цитата:

Цитата Busla
не кривяйтесь »

Видимо, «кривляйтесь». Приношу Вам свои извинения, считайте неудавшейся шуткой.

Цитата:

Цитата Busla
аргументируйте: каким местом PowerShell нефункциональный? и почему он процедурный? »

Хорошо, выражусь иначе: я не вижу существенных отличий в парадигме программирования между WSH и PowerShell (за исключением конвеера). А уж что будет использоваться, If .Test(…) Then … End If или If([RegEx]::IsMatch(…)) {…} — не суть важное.

YuS_2 15-05-2019 22:37 2871932

Цитата:

Цитата Iska
не вижу существенных отличий в парадигме программирования между WSH и PowerShell (за исключением конвеера) »

я бы сказал, что powershell мультипарадигмальный язык, так как в нем явно присутствуют, как минимум, три - функциональная, процедурная и ООП

Iska 15-05-2019 22:50 2871934

YuS_2, в принципе, не споря о деталях, с таким утверждением можно согласиться.

Busla 16-05-2019 13:28 2872005

Цитата:

Цитата Iska
Вопрос останется. Зачем переписывать много…байтный файл, в котором ничего не изменилось? »

по вашему совету надо дважды осуществить поиск по много…байтному файлу
это лишнее, достаточно сравнить результат работы Replace с исходными данными - у вас и так они в памяти и вы надеетесь, что её достаточно
(по идее, если замен не было, должна вернуться ссылка на ту же самую строку)

Цитата:

Цитата Iska
выражусь иначе: я не вижу существенных отличий в парадигме программирования между WSH и PowerShell (за исключением конвеера). »

в таком русле можно сказать и так:
"не вижу существенных отличий в парадигме программирования между C и C++ (за исключением объектов)"

Ну и без смены парадигм у языков есть сложившиеся индивидульные подходы к решению одних и тех же задач.

Iska 16-05-2019 14:14 2872010

Busla, не думаю, что данный способ:
Цитата:

Цитата Busla
достаточно сравнить результат работы Replace с исходными данными - у вас и так они в памяти »

будет работать быстрее.

Цитата:

Цитата Busla
в таком русле можно сказать и так:
"не вижу существенных отличий в парадигме программирования между C и C++ (за исключением объектов)" »

Можно.

Цитата:

Цитата Busla
Ну и без смены парадигм у языков есть сложившиеся индивидульные подходы к решению одних и тех же задач. »

Так что — есть какие-то принципиальные отличия между:
Цитата:

Цитата Iska
If .Test(…) Then … End If или If([RegEx]::IsMatch(…)) {…} »

? Какой тут может быть отличный сложившийся индивидуальный подход к решению одной и той же задачи?

YuS_2 16-05-2019 15:02 2872021

Цитата:

Цитата Iska
Какой тут может быть отличный сложившийся индивидуальный подход к решению одной и той же задачи? »

Речь, видимо о том, что не обязательно заворачивать всё в условный блок. Считываем файл в переменную, результат замены сравниваем уже со значением этой переменной, а по результатам сравнения уже предпринимаем какие-либо действия.
типа:
Код:

$a = '1 2 3 4 5'
# Есть замена
diff $a ($a -replace '3 ') -incl
# Нет изменений
diff $a ($a -replace '8 ') -incl


Iska 16-05-2019 15:37 2872026

YuS_2, спасибо, ясно. Ну, таким макаром и на WSH можно сравнивать. В чём же тут отличия?!

Другое дело, что сравнение оригинального и возможно изменённого содержимого на мой непросвещённый взгляд по времени будет никак не меньше, нежели поиск первого вхождения шаблона. Про наглядность я вообще молчу.

YuS_2 16-05-2019 18:27 2872051

Цитата:

Цитата Iska
Ну, таким макаром и на WSH можно сравнивать. В чём же тут отличия?! »

боюсь, что на wsh это делается не так уж и тривиально...

Цитата:

Цитата Iska
сравнение оригинального и возможно изменённого содержимого на мой непросвещённый взгляд по времени будет никак не меньше, нежели поиск первого вхождения шаблона. »

Можно ведь это дело замерить...
Создаем файл test.txt на 100000 строк, заполненный числами от 0 до 9, по 100 символов в строке...
Код:

$cnt,$cntstr=100000,10
$arr = 0..9
$str = -join (1..$cntstr|%{-join $arr})
1..$cnt|%{$str}|sc test.txt -enc utf8

меняем, скажем, предпоследний символ на букву "a" и запускаем тест:
Код:

'==Условный блок=='
(1..10|%{
        (measure-command{
                if(($a = gc test.txt -raw) -match 'a'){
                        $a -replace 'a'|sc out1.txt -enc utf8
                }
        }).totalseconds
}|measure -aver).average
''
''
'==Сравнение данных=='
(1..10|%{
        (measure-command{
                diff ($a = gc test.txt -raw) ($a -replace 'a')|
                ? SideIndicator -eq '=>'|select -exp inputobject|
                sc out2.txt -enc utf8
        }).totalseconds
}|measure -aver).average

1. файл читается как единая строка, т.е. не построчно, т.к. в рамках этого топика именно такая задача и стояла
2. для более корректного подсчета, каждый тест запускается по 10 раз и вычисляется среднее время...

В сухом остатке:
Получилось, что наоборот, сравнение данных более затратно по времени, в том числе, и в случае если совпадения не существует... хотя отличия вполне сопоставимы...

Цитата:

Цитата Iska
Про наглядность я вообще молчу. »

Наглядность - вещь субъективная и сильно зависит от знания языка.

Iska 16-05-2019 20:14 2872063

Цитата:

Цитата YuS_2
боюсь, что на wsh это делается не так уж и тривиально... »

В смысле? If strSource = strResult Then … End If. Или If StrComp(…) = 0 Then … End If.

Цитата:

Цитата YuS_2
и запускаем тест: »

Не включайте чтение из одного и того же файла в процесс замера.

По остальному пощупаю позже.

YuS_2 16-05-2019 20:55 2872070

Цитата:

Цитата Iska
В смысле? If strSource = strResult Then … End If. Или If StrComp(…) = 0 Then … End If. »

В смысле это только направление, а нужен законченный код, который делает то же самое, что и код на powershell...

Цитата:

Цитата Iska
Не включайте чтение из одного и того же файла в процесс замера. »

Вы можете разделить код на два скрипта и выполнять их в разных процессах... средние показания будут в тех же пределах. Проверьте.
Т.е. это не влияет на результат.

Iska 16-05-2019 22:11 2872077

Цитата:

Цитата YuS_2
В смысле это только направление, а нужен законченный код, который делает то же самое, что и код на powershell... »

Зачем? В смысле — зачем Compare-Object для сравнения на равенство двух строк:
Цитата:

Цитата YuS_2
результат замены сравниваем уже со значением этой переменной, а по результатам сравнения уже предпринимаем какие-либо действия.
типа:
Код:

$a = '1 2 3 4 5'
# Есть замена
diff $a ($a -replace '3 ') -incl
# Нет изменений
diff $a ($a -replace '8 ') -incl

»

?

Вот простая иллюстрация:
Код:

$a = "12345"
$b = "3"

(Measure-Command {
    for($i = 0; $i -le 1000000; $i++) {
        [void](Compare-Object -ReferenceObject $a -DifferenceObject $b -IncludeEqual)
    }
}).TotalSeconds

(Measure-Command {
    for($i = 0; $i -le 1000000; $i++) {
        [void]($a -eq $b)
    }
}).TotalSeconds
64.6133665
2.0294291

Возможно, со строками другой длины и результат будет иной. Но так или иначе, Compare-Object вместо простого сравнения — не лучший выбор.

YuS_2 17-05-2019 08:59 2872099

Цитата:

Цитата Iska
В смысле — зачем Compare-Object для сравнения на равенство двух строк »

А как будем выполнять действие без условного блока? compare-object - по сути, функция, результаты которой мы используем в конвейере, а простое сравнение в конвейер не передать (вернее передать-то можем, но это ничего не даст без того самого условного блока), т.е. в любом случае необходимо использовать оператор ветвления, хоть с -match, хоть с -eq.
Но да, если строка единственная, то никаких преимуществ использование diff не дает, согласен. Compare-object хорош при сравнении массивов, где прямое сравнение работать не будет... но в обсуждаемом случае, построчное чтение не эффективно, по затратам времени, да и фрагмент может ведь располагаться не на одной строке.

В общем, если есть какие-либо дополнения по поводу эффективности, хотелось бы увидеть пояснения на примерах, от автора слов:
Цитата:

Цитата Busla
не надеяться на достаточный объём памяти, а работать построчно
тогда и вопрос перезаписи снимется »


Busla 26-05-2019 15:38 2873068

итак, выходные - прекрасное время для флейма, офтопиков и некропостинга :-)

Признаю: когда я писал про лёгкость операции сравнения, то заблуждался.
В первую очередь я подразумевал оператор '===' из javascript. Но в vbs нет ничего подобного, да и строки там - не ссылочный тип. Впрочем, такой подход не сработает и в javascript - метод replace там всегда возвращает новую строку. В powershell объекты сравниваются по хэшу, но во-первых это не касается строк, во вторых он вычисляется не при создании объекта, а при вызове, поэтому всё равно отдельно перелопачивать весь массив данных.

Что касается приведённых измерений, то Compare-Object, к сожалению, вообще здесь неприменим, как и оператор -eq - они выполняют регистронезависимое сравнение строк. Что к тому же очевидно дольше.

тест скорости сравнения больших строк на PoSh разными методами

Код:

Describe 'Скорость сравнения длинных строк' {

    $times = 100000

    $lorem = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`n"

    $originalString = $lorem * $times + '1'
    $similarString = $lorem * $times + '1'
    $modifiedString = $lorem * $times + '2'

    Context 'сравнение оператором -eq' {

        It 'разных строк' {
            $originalString -eq $modifiedString | Should -BeFalse
        }

        It 'одинаковых строк' {
            $originalString -eq $similarString | Should -BeTrue
        }

        It 'самой себя' {
            $originalString -eq $originalString | Should -BeTrue
        }
    }

    Context 'сравнение оператором -ceq' {

        It 'разных строк' {
            $originalString -ceq $modifiedString | Should -BeFalse
        }

        It 'одинаковых строк' {
            $originalString -ceq $similarString | Should -BeTrue
        }

        It 'самой себя' {
            $originalString -ceq $originalString | Should -BeTrue
        }
    }

    Context 'сравнение методом Compare' {

        It 'разных строк' {
            $originalString.CompareTo($modifiedString) | Should -Be -1
        }

        It 'одинаковых строк' {
            $originalString.CompareTo($similarString) | Should -Be 0
        }

        It 'самой себя' {
            $originalString.CompareTo($originalString) | Should -Be 0
        }
    }

    Context 'сравнение методом Equals' {

        It 'разных строк' -ErrorAction SilentlyContinue {
            $originalString.Equals($modifiedString) | Should -BeFalse
        }

        It 'одинаковых строк' {
            $originalString.Equals($similarString) | Should -BeTrue
        }

        It 'самой себя' {
            $originalString.Equals($originalString) | Should -BeTrue
        }
    }

    Context 'сравнение командлетом Compare-Object' {

        It 'разных строк' {
            Compare-Object $originalString $modifiedString | Should -Not -BeNullOrEmpty
        }

        It 'одинаковых строк' {
            Compare-Object $originalString $similarString | Should -BeNullOrEmpty
        }

        It 'самой себя' {
            Compare-Object $originalString $originalString | Should -BeNullOrEmpty
        }
    }

    Context 'сравнение командлетом Compare-Object -IncludeEqual' {

        It 'разных строк' {
            Compare-Object $originalString $modifiedString -IncludeEqual | Should -Not -BeNullOrEmpty
        }

        It 'одинаковых строк' {
            Compare-Object $originalString $similarString -IncludeEqual | Should -Not -BeNullOrEmpty
        }

        It 'самой себя' {
            Compare-Object $originalString $originalString -IncludeEqual | Should -Not -BeNullOrEmpty
        }
    }

    Context 'сравнение хэшей' {

        It 'разных строк' {
            $originalString.GetHashCode() -eq $modifiedString.GetHashCode() | Should -BeFalse
        }

        It 'одинаковых строк' {
            $originalString.GetHashCode() -eq $similarString.GetHashCode() | Should -BeTrue
        }

        It 'самой себя' {
            $originalString.GetHashCode() -eq $originalString.GetHashCode() | Should -BeTrue
        }
    }

}


результаты теста
Код:

Describing Скорость сравнения длинных строк

  Context сравнение оператором -eq
    [+] разных строк 944ms
    [+] одинаковых строк 84ms
    [+] самой себя 84ms

  Context сравнение оператором -ceq
    [+] разных строк 127ms
    [+] одинаковых строк 87ms
    [+] самой себя 84ms

  Context сравнение методом Compare
    [+] разных строк 725ms
    [+] одинаковых строк 688ms
    [+] самой себя 701ms

  Context сравнение методом Equals
    [+] разных строк 94ms
    [+] одинаковых строк 36ms
    [+] самой себя 9ms

  Context сравнение командлетом Compare-Object
    [+] разных строк 959ms
    [+] одинаковых строк 686ms
    [+] самой себя 677ms

  Context сравнение командлетом Compare-Object -IncludeEqual
    [+] разных строк 717ms
    [+] одинаковых строк 922ms
    [+] самой себя 811ms

  Context сравнение хэшей
    [+] разных строк 110ms
    [+] одинаковых строк 80ms
    [+] самой себя 80ms



Так что доступные скриптовые языки ни прямо, ни косвенно не говорят: была произведена замена или нет (не относится к современному JavaScript - там пишется LastIndex в объект RegExp). Костыльное решение этого вопроса - в качестве аргумента замены использовать не строку, а функцию:
Код:

n=0; 'abcba'.replace(/b/g, function() {n++; return ('B')});
в PoSh это завезли только в версии 6.1:
Код:

$n=@{value = 0}; 'abcba' -replace 'b', { $n.value++; 'B' }
либо в более ранних PoSh использовать .NET класс:
Код:

$n=@{value = 0}; [Regex]::Replace('abcba', 'b', { $n.value++ ; 'B' });
(в нашем конкретном случае счётчик не нужен, достаточно булевого флага: была_замена/не_было)

Цитата:

Цитата YuS_2
В общем, если есть какие-либо дополнения по поводу эффективности, хотелось бы увидеть пояснения на примерах, от автора слов:
Цитата Busla:
не надеяться на достаточный объём памяти, а работать построчно
тогда и вопрос перезаписи снимется »

я о том, что если в память не лезет, то нам надо писать во временный файл, и результат у нас уже присутсвует на диске. Поэтому оригинальный файл переименовывается в .bak, а временный получает имя основного. И так оно как бы правильнее. Вопрос в итоге чисто декоративный, в плане ресурсов бесплатный.
Эффективность считывания в память будет заметна только для определённого диапазона размеров: для мелких незаметно, в случае крупных - ОС всё равно задействует файл подкачки для освобождения оперативки, и мы возвращаемся к медленным дисковым операциям.
И да, я осознаю, что блочные дисковые операции будут значительно быстрее, но такая оптимизация на мой взгляд нужна скорее для завершённых утилит, а не для скиптов, которые должно быть легко понять и поправить.

YuS_2 26-05-2019 22:00 2873125

Пара уточнений:
Цитата:

Цитата Busla
Что касается приведённых измерений, то Compare-Object, к сожалению, вообще здесь неприменим, как и оператор -eq - они выполняют регистронезависимое сравнение строк. »

Почему к сожалению? Это ведь не константа, у diff же есть ключик регистрозависимого сравнения, а оператор -ceq делает это вместо -eq сам...

Цитата:

Цитата Busla
Так что доступные скриптовые языки ни прямо, ни косвенно не говорят: была произведена замена или нет »

косвенно, в powershell, как раз, можно отматчить регэкспом то, что требуется посчитать:
Код:

$a = sls -inp 'abcbadabvbnb' -patt '.b' -all;$a.matches
Но нам-то было интересно, в данном случае, не количество, а скорость...

Busla 27-05-2019 00:20 2873150

Цитата:

Цитата YuS_2
у diff же есть ключик регистрозависимого сравнения »

но ни вы, ни Iska его, к сожалению, не использовали - речь об этом

Цитата:

Цитата YuS_2
косвенно, в powershell, как раз, можно отматчить регэкспом то, что требуется посчитать »

это не косвенно, а отдельная самостоятельная работа/задача, со своим самостоятельным результатом

Цитата:

Цитата YuS_2
Но нам-то было интересно, в данном случае, не количество, а скорость... »

нет
для скорости надо было заниматься оптимизацией операций чтения/записи

YuS_2 27-05-2019 07:57 2873167

Цитата:

Цитата Busla
но ни вы, ни Iska его, к сожалению, не использовали - речь об этом »

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

Цитата:

Цитата Busla
отдельная самостоятельная работа/задача, со своим самостоятельным результатом »

пусть так, но дабы возникнет необходимость получить количественные данные, по крайней мере, такая возможность существует и к тому же, кроме количества, мы ещё и получаем индексы вхождений, в отличие от:
Цитата:

Цитата Busla
Костыльное решение этого вопроса »

======
Цитата:

Цитата Busla
нет »

Что значит нет?!
Повторюсь, мы не гнались за количеством, а практически стройным хором пели:
"Не думай о секундах свысока!"
:)

Цитата:

Цитата Busla
для скорости надо было заниматься оптимизацией операций чтения/записи »

Так вот это-то и хотелось увидеть... для данного, конкретного случая...

Busla 27-05-2019 12:16 2873199

Цитата:

Цитата YuS_2
Цитата Busla:
для скорости надо было заниматься оптимизацией операций чтения/записи »
Так вот это-то и хотелось увидеть... для данного, конкретного случая... »

юмор в том, что "для данного, конкретного случая" это не нужно

этот скрипт получает данные от одной программы и преобразует их для другой
задача/проблема дискового ввода-вывода тут возникает только у людей с пониженной компьютерной грамотностью

YuS_2 27-05-2019 13:21 2873205

Цитата:

Цитата Busla
этот скрипт получает данные от одной программы и преобразует их для другой »

Нет, я о том, что:
Цитата:

Цитата Iska
На PowerShell:
Код: »

и потом:
Цитата:

Цитата Busla
а если гигабайт? »

Цитата:

Цитата Busla
не надеяться на достаточный объём памяти, а работать построчно
тогда и вопрос перезаписи снимется »

Т.е. в данном, конкретном случае, как избежать перезаписи файла, если нет фактических изменений данных?

Busla 27-05-2019 15:55 2873221

YuS_2, если буквально, то при построчной обработке вы не можете ПЕРЕзаписывать файл, избегать нечего
если подробно - конец 31го комментария

YuS_2 27-05-2019 17:45 2873241

Цитата:

Цитата Busla
то при построчной обработке вы не можете ПЕРЕзаписывать файл, избегать нечего»

А, в этом смысле... тогда понятно. Спасибо.


Время: 22:51.

Время: 22:51.
© OSzone.net 2001-