Показать полную графическую версию : findstr при записи в тот же файл
Всё! Товарищ один помог, все недостатки for исправляются параметрами »
Зачем?
Зачем демонстрировать свою, как бы это сказать помягче... неосведомленность, в форме утверждений?
Задавай лучше вопросы, найдутся люди - подскажут обязательно... может быть не сразу, но подскажут.
Во-первых:
The maximum individual environment variable size is 8192bytes
расшифровать, что это означает?
Вот тебе рабочий вариант:
for /f "delims=" %%a in ('findstr /ivc:"192.168.1.101" test.txt^&del test.txt') do >>test.txt echo %%a
с пустыми строками разбирайся сам...
Во-вторых:
выше уже подсказали возможные траблы.
В-третьих:
Как я уже говорил, скорость обработки, также никуда не денется...
Тот вариант с промежуточным файлом, который предложен выше, обрабатывает файл в ~100000 строк (~1,2Mb) за:
Start: 24.08.2018 9:20:41,81
Stop: 24.08.2018 9:20:42,17
причем все символы и пустые строки сохраняются...
В общем, всё остальное (на cmd, естественно), при такой постановке задачи - от лукавого... даже если возникнет иллюзия нормальной работы. ;-)
megaloman
24-08-2018, 14:54
@set @E=1; /*
@Echo Off
cls
Set "FileIn=Z:\Box_In\Улицы разбитых фонарей 22.txt"
Set "DelFind=192.168.1.101"
Cscript //NoLogo /E:jscript "%~dpnx0" "%FileIn%" "%DelFind%"
pause
GoTo :Eof
*/
var oArg = WScript.Arguments;
var nArg = oArg.Count();
if (nArg < 2) {
WScript.Echo("Error! Invalid number of arguments!");
WScript.Quit(240);
}
var FText=oArg(0);
var FSO=WScript.CreateObject("Scripting.FileSystemObject");
var InFile;
try {InFile = FSO.OpenTextFile(FText,1);}
catch (e) {
if (e !=0 ) {
WScript.Echo("Error! " + FText + " " + e.description);
WScript.Quit(1);
}
}
var TextAll = InFile.ReadAll();
InFile.Close();
var i0 = TextAll.indexOf(oArg(1));
if (i0 < 0) {
WScript.Echo("Error! String not found! \n" + oArg(1));
WScript.Quit(2);
}
var C10=String.fromCharCode(10);
var i1 = TextAll.lastIndexOf(C10,i0);
var i2 = TextAll.indexOf(C10,i0);
if (i1 < 0 && i2 < 0) {
TextAll="";
}
else
{
if (i2 < 0) {TextAll=TextAll.substring(0,i1+1)};
if (i1 <= 0) {TextAll = TextAll.substring(i2+1,TextAll.length)};
if (i1 >0 && i2 >= 0) {TextAll=TextAll.substring(0,i1+1) + TextAll.substring(i2+1,TextAll.length)};
}
InFile = FSO.OpenTextFile(FText,2);
InFile.Write(TextAll);
InFile.Close();
megaloman, если пользовать JScript, то удобнее регуляркой.
megaloman
24-08-2018, 16:33
если пользовать JScript, то удобнее регуляркой »в этой задаче - какая в них радость?
Не грубите писателю, он пишет как умеет »
:) :up
без некошерного создания второго файла »
длинный код »
тогда кошерный и короткий powershell:
(gc test.txt -raw) -replace '(?<=^|\n)[^\n]*192\.168\.1\.101[^\n]*\n'|sc test.txt -non
:drug:
какая в них радость? »
код будет значительно короче...
в этой задаче - какая в них радость? »
В использовании одного .test() и одного .replace(). Это ведь вроде как должно быть проще, не?
тогда кошерный и короткий powershell: »
Я таки ратую за присутствие в коде аналога .test() — ::IsMatch(), дабы не переписывать файл при отсутствии замен.
megaloman
24-08-2018, 19:55
Iska, Я делал задачу для случая, когда искомая подстрока входит в строку, которую надо удалить. Строка в любом месте текста, может быть первая, может быть последняя. Реплейс, конечно, заманчиво, но не сообразил, как нарисовать регулярку, напряжно ...
Как альтернатива, читать текст построчно
Я Вам нарисую, но только для VBScript, без файла и без каких-либо проверок, а Вы сами тогда на JScript переведёте, лады? Мой JScript оставляет желать лучшего.
Option Explicit
Dim strContent
strContent = _
"192.168.1.98" & vbCrLf & _
"192.168.1.99" & vbCrLf & _
"192.168.1.100" & vbCrLf & _
"192.168.1.101" & vbCrLf & _
"#####192.168.1.101" & vbCrLf & _
"192.168.1.101#####" & vbCrLf & _
"#####192.168.1.101#####" & vbCrLf & _
"192.168.1.102" & vbCrLf & _
"192.168.1.103" & vbCrLf & _
"192.168.1.104" & vbCrLf
WScript.Echo _
"--- Before: -----------------------------" & vbCrLf & _
strContent & vbCrLf & _
"-----------------------------------------" & vbCrLf
With WScript.CreateObject("VBScript.RegExp")
.Pattern = "^.*192\.168\.1\.101.*$\n"
.Global = True
.MultiLine = True
If .Test(strContent) Then
strContent = .Replace(strContent, "")
WScript.Echo _
"--- After: ------------------------------" & vbCrLf & _
strContent & vbCrLf & _
"-----------------------------------------" & vbCrLf
Else
WScript.Echo "Not found pattern [" & .Pattern & "]."
End If
End With
WScript.Quit 0
https://i.imgur.com/COWqHWV.png
P.S. Не сработает только для одного случая — когда «192.168.1.101» будет в последней строке, и эта строка не будет завершаться символами конца строки.
Я таки ратую за присутствие в коде »
понимаю, принимаю и всегда только за... это ведь несложно организовать, ежели возникнет такая необходимость, например так:
$re = '(?<=\A|\n)[^\n]*192\.168\.1\.101[^\n]*(\n|\Z)'
if(($a = gc test.txt -raw) -match $re){$a -replace $re|sc test.txt -non}
Не сработает только для одного случая — когда «192.168.1.101» будет в последней строке »
Кстати, да, у меня тоже не было учтено...
Но PCRE-совместимые регулярки - вещь в себе, т.е. достаточно универсальны, в основном...
Этот момент легко решается с помощью \Z
Реплейс, конечно, заманчиво, но не сообразил, как нарисовать регулярку, напряжно ...
Как альтернатива, читать текст построчно »
Можете взять за основу шаблон из версии для PoSh...
Читать и парсить текст построчно, при достаточно большом объеме - тоскливое занятие (по скорости), хоть и более привлекательное, с точки зрения настраиваемости обработки.
megaloman
24-08-2018, 22:40
Iska, прочесть файл в строку, добавить конец строки в конец, обработать, что получилось - записать без последнего символа. Всё отработает, но задачка получается очень частная: в моём тупом подходе - я даю скрипту подстроку произвольного вида. Если делать регулярку - получаем частное решение. Но красивое.
Наверное, если передавать js (=vbs) скрипту не подстроку для поиска, а рег. выражение, то прокатит.
это ведь несложно организовать, ежели возникнет такая необходимость, например так: »
Ну, вот — можете же ;).
Но PCRE-совместимые регулярки - вещь в себе, т.е. достаточно универсальны, в основном...
Этот момент легко решается с помощью \Z »
Таки да. Добавляем в конец шаблона после символа «\n» символ «?»:
Option Explicit
Dim strContent
strContent = _
"192.168.1.101" & vbCrLf & _
"192.168.1.98" & vbCrLf & _
"192.168.1.99" & vbCrLf & _
"192.168.1.100" & vbCrLf & _
"192.168.1.101" & vbCrLf & _
"#####192.168.1.101" & vbCrLf & _
"192.168.1.101#####" & vbCrLf & _
"#####192.168.1.101#####" & vbCrLf & _
"192.168.1.102" & vbCrLf & _
"192.168.1.103" & vbCrLf & _
"192.168.1.104" & vbCrLf & _
"192.168.1.101"
WScript.Echo _
"--- Before: -----------------------------" & vbCrLf & _
strContent & vbCrLf & _
"-----------------------------------------" & vbCrLf
With WScript.CreateObject("VBScript.RegExp")
.Pattern = "^.*192\.168\.1\.101.*$\n?"
.Global = True
.MultiLine = True
If .Test(strContent) Then
strContent = .Replace(strContent, "")
WScript.Echo _
"--- After: ------------------------------" & vbCrLf & _
strContent & vbCrLf & _
"-----------------------------------------" & vbCrLf
Else
WScript.Echo "Not found pattern [" & .Pattern & "]."
End If
End With
WScript.Quit 0
и:
https://i.imgur.com/z6JTowl.png
Можете взять за основу шаблон из версии для PoSh... »
Напрямую не выйдет, слишком разные возможности в регулярках.
я даю скрипту подстроку произвольного вида. »
Да, к сожалению, в WSH нет такого хорошего средства, как метод Regex.Escape(String) Method (System.Text.RegularExpressions) | Microsoft Docs (https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.escape?view=netframework-4.7.2) в .Net.
Ну, вот — можете же »
Да тут дело не в умении/не умении, это достаточно простая операция, а потому не очень интересная... :)
Добавляем в конец шаблона после символа «\n» символ «?»: »
Все же, в этом случае, лучше так:
[^\n]*192\.168\.1\.101[^\n]*\n?
потому как, в случае чтения текста единым массивом, .* со своей жадностью (особенно в случае (?s) ) может привести к неожиданным результатам, при \n? в конце шаблона.
Напрямую не выйдет, слишком разные возможности в регулярках. »
Это да, вольные и урезанные реализации - зло, но тут и не надо напрямую, просто взять за основу...
потому как, в случае чтения текста единым массивом, .* со своей жадностью (особенно в случае (?s) ) может привести к неожиданным результатам, при \n? в конце шаблона. »
Неа. Там ведь перед \n есть $. То есть, это — «конец строки, за которым сразу может следовать символ конца строки, а может и не следовать», вот такая интересная логика :). Разумеется, это справедливо и работает только для установки:
.MultiLine = True
когда ^ и $ рассматриваются как «начало строки» и «конец строки», а не «начало текста» и «конец текста».
Там ведь перед \n есть $ »
А, ну тоже верно... только это более частный случай, т.е. необходимо учитывать это обязательно.
А это:
[^\n]*192\.168\.1\.101[^\n]*\n?
будет работать, при любом .MultiLine
Не по теме: без findstr cmd+js без некошерного создания второго файла, пустые строки сохраняются, всякие непристойные символы сохраняются и не мешают. По сравнению с голым cmd длинный код
Удаляем строку, содержащую указанную подстроку
Не грубите писателю, он пишет как умеет
Ооо, а вот это именно то, что было нуно, готовое решение прямо таки!
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.