Войти

Показать полную графическую версию : findstr при записи в тот же файл


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

YuS_2
24-08-2018, 06:26
Всё! Товарищ один помог, все недостатки 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();

Iska
24-08-2018, 15:30
megaloman, если пользовать JScript, то удобнее регуляркой.

megaloman
24-08-2018, 16:33
если пользовать JScript, то удобнее регуляркой »в этой задаче - какая в них радость?

YuS_2
24-08-2018, 16:56
Не грубите писателю, он пишет как умеет »
:) :up

без некошерного создания второго файла »
длинный код »
тогда кошерный и короткий powershell:
(gc test.txt -raw) -replace '(?<=^|\n)[^\n]*192\.168\.1\.101[^\n]*\n'|sc test.txt -non
:drug:

какая в них радость? »
код будет значительно короче...

Iska
24-08-2018, 19:46
в этой задаче - какая в них радость? »
В использовании одного .test() и одного .replace(). Это ведь вроде как должно быть проще, не?

тогда кошерный и короткий powershell: »
Я таки ратую за присутствие в коде аналога .test() — ::IsMatch(), дабы не переписывать файл при отсутствии замен.

megaloman
24-08-2018, 19:55
Iska, Я делал задачу для случая, когда искомая подстрока входит в строку, которую надо удалить. Строка в любом месте текста, может быть первая, может быть последняя. Реплейс, конечно, заманчиво, но не сообразил, как нарисовать регулярку, напряжно ...
Как альтернатива, читать текст построчно

Iska
24-08-2018, 20:30
Я Вам нарисую, но только для 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» будет в последней строке, и эта строка не будет завершаться символами конца строки.

YuS_2
24-08-2018, 22:35
Я таки ратую за присутствие в коде »
понимаю, принимаю и всегда только за... это ведь несложно организовать, ежели возникнет такая необходимость, например так:
$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) скрипту не подстроку для поиска, а рег. выражение, то прокатит.

Iska
24-08-2018, 22:50
это ведь несложно организовать, ежели возникнет такая необходимость, например так: »
Ну, вот — можете же ;).

Но 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.

YuS_2
24-08-2018, 23:32
Ну, вот — можете же »
Да тут дело не в умении/не умении, это достаточно простая операция, а потому не очень интересная... :)

Добавляем в конец шаблона после символа «\n» символ «?»: »
Все же, в этом случае, лучше так:
[^\n]*192\.168\.1\.101[^\n]*\n?
потому как, в случае чтения текста единым массивом, .* со своей жадностью (особенно в случае (?s) ) может привести к неожиданным результатам, при \n? в конце шаблона.

Напрямую не выйдет, слишком разные возможности в регулярках. »
Это да, вольные и урезанные реализации - зло, но тут и не надо напрямую, просто взять за основу...

Iska
24-08-2018, 23:58
потому как, в случае чтения текста единым массивом, .* со своей жадностью (особенно в случае (?s) ) может привести к неожиданным результатам, при \n? в конце шаблона. »
Неа. Там ведь перед \n есть $. То есть, это — «конец строки, за которым сразу может следовать символ конца строки, а может и не следовать», вот такая интересная логика :). Разумеется, это справедливо и работает только для установки:
.MultiLine = True
когда ^ и $ рассматриваются как «начало строки» и «конец строки», а не «начало текста» и «конец текста».

YuS_2
25-08-2018, 00:11
Там ведь перед \n есть $ »
А, ну тоже верно... только это более частный случай, т.е. необходимо учитывать это обязательно.
А это:
[^\n]*192\.168\.1\.101[^\n]*\n?
будет работать, при любом .MultiLine

TolikD
27-08-2018, 21:43
Не по теме: без findstr cmd+js без некошерного создания второго файла, пустые строки сохраняются, всякие непристойные символы сохраняются и не мешают. По сравнению с голым cmd длинный код
Удаляем строку, содержащую указанную подстроку
Не грубите писателю, он пишет как умеет

Ооо, а вот это именно то, что было нуно, готовое решение прямо таки!




© OSzone.net 2001-2012