Войти

Показать полную графическую версию : [решено] Необходимо найти все строки которые начинаются с "download:"https:" и заканчиваются


Страниц : 1 [2]

Iska
15-05-2019, 22:50
YuS_2, в принципе, не споря о деталях, с таким утверждением можно согласиться.

Busla
16-05-2019, 13:28
Вопрос останется. Зачем переписывать много…байтный файл, в котором ничего не изменилось? »
по вашему совету надо дважды осуществить поиск по много…байтному файлу
это лишнее, достаточно сравнить результат работы Replace с исходными данными - у вас и так они в памяти и вы надеетесь, что её достаточно
(по идее, если замен не было, должна вернуться ссылка на ту же самую строку)

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

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

Iska
16-05-2019, 14:14
Busla, не думаю, что данный способ:
достаточно сравнить результат работы Replace с исходными данными - у вас и так они в памяти »
будет работать быстрее.

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

Ну и без смены парадигм у языков есть сложившиеся индивидульные подходы к решению одних и тех же задач. »
Так что — есть какие-то принципиальные отличия между:
If .Test(…) Then … End If или If([RegEx]::IsMatch(…)) {…} »
? Какой тут может быть отличный сложившийся индивидуальный подход к решению одной и той же задачи?

YuS_2
16-05-2019, 15:02
Какой тут может быть отличный сложившийся индивидуальный подход к решению одной и той же задачи? »
Речь, видимо о том, что не обязательно заворачивать всё в условный блок. Считываем файл в переменную, результат замены сравниваем уже со значением этой переменной, а по результатам сравнения уже предпринимаем какие-либо действия.
типа:
$a = '1 2 3 4 5'
# Есть замена
diff $a ($a -replace '3 ') -incl
# Нет изменений
diff $a ($a -replace '8 ') -incl

Iska
16-05-2019, 15:37
YuS_2, спасибо, ясно. Ну, таким макаром и на WSH можно сравнивать. В чём же тут отличия?!

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

YuS_2
16-05-2019, 18:27
Ну, таким макаром и на WSH можно сравнивать. В чём же тут отличия?! »
боюсь, что на wsh это делается не так уж и тривиально...

сравнение оригинального и возможно изменённого содержимого на мой непросвещённый взгляд по времени будет никак не меньше, нежели поиск первого вхождения шаблона. »
Можно ведь это дело замерить...
Создаем файл 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
16-05-2019, 20:14
боюсь, что на wsh это делается не так уж и тривиально... »
В смысле? If strSource = strResult Then … End If. Или If StrComp(…) = 0 Then … End If.

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

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

YuS_2
16-05-2019, 20:55
В смысле? If strSource = strResult Then … End If. Или If StrComp(…) = 0 Then … End If. »
В смысле это только направление, а нужен законченный код, который делает то же самое, что и код на powershell...

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

Iska
16-05-2019, 22:11
В смысле это только направление, а нужен законченный код, который делает то же самое, что и код на powershell... »
Зачем? В смысле — зачем Compare-Object для сравнения на равенство двух строк:
результат замены сравниваем уже со значением этой переменной, а по результатам сравнения уже предпринимаем какие-либо действия.
типа:
$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
В смысле — зачем Compare-Object для сравнения на равенство двух строк »
А как будем выполнять действие без условного блока? compare-object - по сути, функция, результаты которой мы используем в конвейере, а простое сравнение в конвейер не передать (вернее передать-то можем, но это ничего не даст без того самого условного блока), т.е. в любом случае необходимо использовать оператор ветвления, хоть с -match, хоть с -eq.
Но да, если строка единственная, то никаких преимуществ использование diff не дает, согласен. Compare-object хорош при сравнении массивов, где прямое сравнение работать не будет... но в обсуждаемом случае, построчное чтение не эффективно, по затратам времени, да и фрагмент может ведь располагаться не на одной строке.

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

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

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

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



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' });
(в нашем конкретном случае счётчик не нужен, достаточно булевого флага: была_замена/не_было)

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

YuS_2
26-05-2019, 22:00
Пара уточнений:
Что касается приведённых измерений, то Compare-Object, к сожалению, вообще здесь неприменим, как и оператор -eq - они выполняют регистронезависимое сравнение строк. »
Почему к сожалению? Это ведь не константа, у diff же есть ключик регистрозависимого сравнения, а оператор -ceq делает это вместо -eq сам...

Так что доступные скриптовые языки ни прямо, ни косвенно не говорят: была произведена замена или нет »
косвенно, в powershell, как раз, можно отматчить регэкспом то, что требуется посчитать:
$a = sls -inp 'abcbadabvbnb' -patt '.b' -all;$a.matches
Но нам-то было интересно, в данном случае, не количество, а скорость...

Busla
27-05-2019, 00:20
у diff же есть ключик регистрозависимого сравнения »
но ни вы, ни Iska его, к сожалению, не использовали - речь об этом

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

Но нам-то было интересно, в данном случае, не количество, а скорость... »
нет
для скорости надо было заниматься оптимизацией операций чтения/записи

YuS_2
27-05-2019, 07:57
но ни вы, ни Iska его, к сожалению, не использовали - речь об этом »
то, что не использовали, это не говорит ведь о том, что это невозможно... а то, что регистрозависимый поиск быстрее, подразумевается по умолчанию.

отдельная самостоятельная работа/задача, со своим самостоятельным результатом »
пусть так, но дабы возникнет необходимость получить количественные данные, по крайней мере, такая возможность существует и к тому же, кроме количества, мы ещё и получаем индексы вхождений, в отличие от:
Костыльное решение этого вопроса »
======
нет »
Что значит нет?!
Повторюсь, мы не гнались за количеством, а практически стройным хором пели:
"Не думай о секундах свысока!"
:)

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

Busla
27-05-2019, 12:16
Цитата Busla:
для скорости надо было заниматься оптимизацией операций чтения/записи »
Так вот это-то и хотелось увидеть... для данного, конкретного случая... »
юмор в том, что "для данного, конкретного случая" это не нужно

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

YuS_2
27-05-2019, 13:21
этот скрипт получает данные от одной программы и преобразует их для другой »
Нет, я о том, что:
На PowerShell:
Код: »
и потом:
а если гигабайт? »
не надеяться на достаточный объём памяти, а работать построчно
тогда и вопрос перезаписи снимется »
Т.е. в данном, конкретном случае, как избежать перезаписи файла, если нет фактических изменений данных?

Busla
27-05-2019, 15:55
YuS_2, если буквально, то при построчной обработке вы не можете ПЕРЕзаписывать файл, избегать нечего
если подробно - конец 31го комментария (http://forum.oszone.net/post-2873068-31.html)

YuS_2
27-05-2019, 17:45
то при построчной обработке вы не можете ПЕРЕзаписывать файл, избегать нечего»
А, в этом смысле... тогда понятно. Спасибо.




© OSzone.net 2001-2012