Показать полную графическую версию : [решено] Удаление нежелательных символов из строки.
Доброго времени суток уважаемые форумчане, в процессе написания батника возникла задача - очистить строки от нежелательных символов. Нежелательные символы, в идеале, это - !"№@#$^&*\|/?:%<~>` Частично проблема решается, но не со всеми символами прокатывает. Например &,%,<,>,| и " (двойная кавычка) ведут себя странновато. Подскажите способ их аккуратно извлечь и удалить не потеряв исходный текст, учитывая что строки читаются из файла, нельзя предугадать появление символов и нет возможности экранировать их в файле. Пример того что уже есть:
IN:
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
chcp 866>nul
rem ...обрабатываемый текст построчно читается из файла и имеет примерно следующий вид
set str=some *long:: ##\text %@and ~more /more !more "этот текст просто обрежется из-за кавычки
call :clean_out_str %str%
echo исходная строка - "%str%"
echo результат - "%clean_str%"
pause >nul
exit
:clean_out_str <str_for_clean>
set this_str=%*
set clean_str=
set /a char_counter=0
rem поиск и удаление нежелательных символов
:del_unwanted_chars
for /f "delims=" %%l in ("!this_str:~%char_counter%,1!") do (
set current_char=%%~l
if "!current_char!" NEQ "" (
for /f %%f in ('echo "!current_char!"^|findstr /i /r "[\\|/?:*#@!%&~$<>]"') do (
echo.%%f
if %%f NEQ "" (
set current_char=
goto :next
)
)
:next
set clean_str=!clean_str!!current_char!
set /a char_counter+=1
goto :del_unwanted_chars
)
)
exit /b
ENDLOCAL
OUT:
"*"
":"
":"
"#"
"#"
"\"
"@"
"~"
"/"
исходная строка - "some *long:: ##\text @and ~more /more more "этот текст просто обрежется из-за кавычки"
результат - "some long text and more more more "
Возможно есть альтернативные решения...
megaloman
25-10-2018, 17:32
FileIn = "Z:\Box_In\Большой txt файл.txt"
harm = "!""№@#$^&*\|/?:%<~>`"
useful = " "
Set FSO = CreateObject("Scripting.FileSystemObject")
Set fIn = FSO.OpenTextFile(FileIn, 1, False) ', -2)
Alls = fIn.ReadAll
fIn.Close
For i = 1 To Len(harm)
Alls = Replace(Alls, Mid(harm, i, 1), useful)
Next
Set fIn = FSO.CreateTextFile(FileIn, True)
fIn.Write Alls
fIn.CloseЗдесь нежелательные символы заменяются пробелами
megaloman
25-10-2018, 20:10
в процессе написания батника »Зачем нужен батник, пока не ясно, какая суперзадача? В CMD имхо замену всех символов из этого набора сделать нельзя. Если принципиально использовать cmd, то можно совместить bat-файл с функцией в виде скрипта js, который эту замену сделает. И можно всё остальное ваять в CMD (между /* и */).@set @E=1; /*
@Echo Off
cls
chcp 866 >nul
Set "FileIn=Z:\Box_In\Большой txt файл.txt"
Echo "%FileIn%"
Cscript //NoLogo /E:jscript "%~dpnx0" "%FileIn%"
Pause
GoTo :Eof
*/
var FileIn = WScript.Arguments(0);
//WScript.Echo(FileIn);
//var harm = '!"╣@#$^&*\\|/?:%<~>`';
var harm = '!"№@#$^&*\\|/?:%<~>`';
var useful = " ";
var lharm=harm.length;
var FSO = WScript.CreateObject("Scripting.FileSystemObject");
var fIn = FSO.OpenTextFile(FileIn, 1, false);
var Alls = fIn.ReadAll();
fIn.Close();
for(var i=0; i<lharm; i++) {
Alls = Alls.replace(new RegExp('\\'+harm.substr(i,1),'g'),useful);
}
fIn = FSO.CreateTextFile(FileIn, true);
fIn.Write(Alls);
fIn.Close();
Amunrah, в CMD это сделать невозможно (имхо). Вот VBS »
Жаль что в CMD не получится. C VBS как-то не сталкивался, но судя по примеру, вроде не очень сложно, и, как бы ни хотелось реализовать все функционалом батника, видимо буду двигаться в сторону VBS. Спасибо за оперативный ответ и рабочий пример.
Зачем нужен батник, пока не ясно, какая суперзадача? В CMD имхо замену всех символов из этого набора сделать нельзя. Если принципиально использовать cmd, то можно совместить bat-файл с функцией в виде скрипта js, который эту замену сделает. И можно всё остальное ваять в CMD (между /* и */). »
Батник нужен для запуска на машинах юзверей (с разной виндой - от XP до 10-ки), доустановить на которые что-либо не получится. Кстати вариант с js мне кажется очень подходящим. Надо обкатать в работе на разных машинках )
bat c вызовом js »
Все работает, но не очень дружит с русским текстом, удаляет букву т и букву Д - если файл в OEM866 кодировке, при кодировке UTF-8 такого не наблюдается, но буква ф превращается в знак вопроса (пока только это заметил, возможно, что так только у меня...)
Amunrah, для каждой кодировки — свой подход нужен. А про пакетные файлы здесь вообще забудьте: только WSH или PowerShell.
как правильно заметил megaloman в cmd сложно сделать подобные вещи, но можно сделать просто предупреждающий bat.
Например есть файл, в строках которого мы не уверены, но хотим их использовать для имен файлов или папок, поможет такой bat:
(использованы, соответственно символы, запрещенные системой для имен)
@echo off
set "f=file.txt"
set "ss=* < > \ / | ? :"
<"%f%" (for /f "delims=" %%a in ('more') do @call :# "%%a")
pause& exit
:#
for /f "delims=" %%a in ('cmd /v/c echo !ss!') do echo "%~1"|>nul findstr "%%a" && (
<nul set /p="Есть запрещенный символ из состава: [%ss%] в строке: %~1"& echo:
) || (
md "%~1"
)
exit /b
megaloman
26-10-2018, 00:36
Amunrah, удаляет букву т и букву Д - если файл в OEM866 кодировке »У меня не удаляет. Батник с js и текст в 866 кодировке. Прикрепил к сообщению. (переименовал в txt).
vbs в 1251 кодировке и текст в 866 кодировке тоже работают, но строку для замены пришлось подшаманить, чтобы № заменялся. Прикрепил к сообщению. (переименовал в txt).
Если в Вашем тексте нет гос секретов и вмешательства в американские выборы, хотелось бы протестировать решения на Вашем реальном файле.
И, однозначно, при разных кодировках файлов надо подбирать, как сохранить строку заменяемых символов - её кодировка должна совпадать с кодировкой файла.
По видимому, корректнее задавать эту строку в виде массива кодов символов.
По видимому, корректнее задавать эту строку в виде массива кодов символов. »
Дык, всё равно нужно будет знать кодировку исходного файла.
megaloman
26-10-2018, 08:14
Iska, каждая задача должна иметь конечный смысл. Замена символов в файле - не конечная цель. Не может быть, чтобы на разных машинах файл для суперзадачи приходит в разных кодировках. Как не изгаляйся, останется вопрос: а зачем всё это нужно?Я еще могу пытаться телепатить, но заставить телепатить скрипт я не готов
Если в Вашем тексте нет гос секретов и вмешательства в американские выборы, хотелось бы протестировать решения на Вашем реальном файле.
И, однозначно, при разных кодировках файлов надо подбирать, как сохранить строку заменяемых символов - её кодировка должна совпадать с кодировкой файла.
По видимому, корректнее задавать эту строку в виде массива кодов символов. »
Никаких гос-секретов )) Все гораздо прозаичнее. Хотя подобные штуки уже есть, но, по разным причинам, решил написать свой инструмент для архивирования файловых инфобаз 1с. BAT-ник мал да удал и работает везде. Вобщем - если вам интересно в двух словах - тулза, являясь частью системы автоматизации, формирует меню выбора в виде списка баз на основе файлика ibases.v8i, в котором, среди прочего, хранятся имена и пути. Сам файл, насколько я понял, всегда имеет кодировку utf-8 c bom, поэтому приходится сначала конвертить его в cp866 во временный файл и только потом уже парсить. Это для совместимости батника с WinXP (конвертирую с помощью win_iconv). В результате все просто - нужно лишь выбрать информационную базу из списка меню, а все пути подставятся сами и она благополучно улетит в датированный архив (через 7zip_extra) в подкаталог с именем базы. (это быстро и удобно + сама 1С, во избежание, рекомендует делать архивы копированием, а не выгрузкой - https://its.1c.ru/db/metod8dev#content:2922:hdoc)
Проблемы появляются, когда пользователь с фантазией не скучно и не стандартно обзывает свои базы, поэтому и возникает необходимость прогонять некоторые строки файла через фильтр. Если подходить строго, то удалять нужно символы, которые нельзя использовать в путях, но задача показалась мне интересной и для универсальности хотелось бы менять набор символов в широком диапазоне.
п.с. Понимаю, что практически на любом другом интерпретируемом языке реализовать подобное не составило бы большого труда, однако нужно чтобы и работало на любом компе.
п.п.с Файлик во вложении
Задача оказалась решаемой. Просто нужно быть аккуратнее с синтаксисом. Оставлю тут, может кому-то тоже пригодится:
IN:
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
chcp 866>nul
rem ...обрабатываемый текст построчно читается из файла и имеет примерно следующий вид
set "str=some *long:?: $long #&#\te=^^xt <%@and |~№more /more> !more"
call :clean_out_str "%str%"
echo исходная строка - "%str%"
echo результат - %clean_str:"=%
pause >nul
exit
:clean_out_str <str_for_clean>
set this_str=%*
set clean_str=
set /a char_counter=0
rem поиск и удаление нежелательных символов
:del_unwanted_chars
for /f "delims=" %%l in ("!this_str:~%char_counter%,1!") do (
set current_char=%%~l
if !current_char! NEQ "" (
for /f %%f in ('echo "!current_char!"^|findstr /r "[\\|/?:*#^^=@!%&~$<>№]"') do (
echo.%%f
if %%f NEQ "" (
set current_char=
)
)
set clean_str=!clean_str!!current_char!
set /a char_counter+=1
goto :del_unwanted_chars
)
)
exit /b
ENDLOCAL
OUT:
"*"
":"
"?"
":"
"$"
"#"
"&"
"#"
"\"
"="
"^"
"^"
"<"
"@"
"|"
"~"
"№"
"/"
">"
исходная строка - "some *long:?: $long #&#\te=^xt <@and |~№more /more> more"
результат - some long long text and more more more
Только кавычки приходится удалять стандартно %result:"=% Тут пример с заданной строкой, поэтому не получается использовать кавычки не экранируя их, но при чтении строк циклом из файла проблем не возникло. Единственное не удалось победить восклицательный и знак процента - по одиночке они пропадают сами, а в паре вырезают часть заключенного в них текста, не понятно как запретить интерпретатору считать их частью переменной. Но, думаю, это мелочи... радует сам факт, и cmd, как оказалось, не так уж плох )
Amunrah,
кроме парных кавычек проблемы с удалением может доставить знак "="
еще почему-то нет "^", хотя тоже проблемный символ.
вообще как по мне достаточно варианта что я приводил из п7, проблемные строки просто игнорируются с выводом на экран и если учесть что проблемные строки из вашего файла претерпевают изменение, то небольшая разница с игнорированием или можно сделать замену на "name(N+1)"
alpap:
Amunrah,
кроме парных кавычек проблемы с удалением может доставить знак "="
еще почему-то нет "^", хотя тоже проблемный символ.
вообще как по мне достаточно варианта что я приводил из п7, проблемные строки просто игнорируются с выводом на экран и если учесть что проблемные строки из вашего файла претерпевают изменение, то небольшая разница с игнорированием или можно сделать замену на "name(N+1)" »
Да, вы правы, во многих случаях вполне достаточно вашего варианта, но это скорее обходной маневр,а мне просто хотелось разобраться в проблеме... )
Дополнил регулярку - [\\|/?:*#^^=@!%&~$<>] - при чтении из файла срабатывает нормально, однако если задавать строку в батнике, то символ ^ нужно экранировать ^^
Не может быть, чтобы на разных машинах файл для суперзадачи приходит в разных кодировках. »
Именно так.
Как не изгаляйся, останется вопрос: а зачем всё это нужно? »
Я пишу проще: «нахрена?» :lol:.
Amunrah, многое из того, что Вы выбрасываете, вполне допустимо в путях и именах файлов: Naming Files, Paths, and Namespaces | Microsoft Docs (https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file). И да — разворачиваете на Windows XP PowerShell 2.0 и перестаёте заниматься извращениями на пакетных файлах ([System.IO.Path]::GetInvalidPathChars()/[System.IO.Path]::GetInvalidFileNameChars()).
Iska
Amunrah, многое из того, что Вы выбрасываете, вполне допустимо в путях и именах файлов: Naming Files, Paths, and Namespaces | Microsoft Docs. И да — разворачиваете на Windows XP PowerShell 2.0 и перестаёте заниматься извращениями на пакетных файлах ([System.IO.Path]::GetInvalidPathChars()/[System.IO.Path]::GetInvalidFileNameChars()). »
Кто же спорит, но я ведь уже писал, что такой набор символов был выбран интереса ради и общей пользы для. В итоге с удалением недопустимых знаков батник справляется на ура плюс имеет некоторую гибкость и универсальность. Естественно на своем железе можно развернуть вообще все что угодно, вопрос выбора CMD возникает когда нужно автоматизировать рутину на куче чужих машин, где что-то устанавливать, как минимум, лишняя потеря времени...
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.