Показать полную графическую версию : Как добавить текст в середину текстрового файла
amel27, А можно ли так же использовать переменную для имени параметра, то есть в данном примере вместо ссс. Так работать не хочет: set "$ByRef="a 1","b 2","c 3""
set "$val="a 1","b 2","c 3""
CALL:INISET 1.ini paste $ByRef $val
можно ли так же использовать переменную для имени параметра »можно совместить оба способа (по аналогии):
@echo off
set "$par=ccc"
set "$val="a 1","b 2","c 3""
CALL:INISET 1.ini paste $par $val
EXIT
:INISET %file_path% %section% parm val
::---------------------------------------
SETLOCAL DisableDelayedExpansion
set $sn= & set $vf=0& set "$ft=%TEMP%\%RANDOM%%RANDOM%.tmp"
(for /f "tokens=1,2* delims==:" %%a in ('findstr /n "$" "%~1"') do (
set "$b=%%b"& set "$c=%%c"
SETLOCAL EnableDelayedExpansion
if defined %~3 (set $3=!%~3!) else set "$3=%~3"
if defined %~4 (set $4=!%~4!) else set "$4=%~4"
if "!$b:~0,1!"=="[" set "$sn=!$b:~1,-1!"
set $lf=_& if /i "!$sn!"=="%~2" if /i "!$b!"=="!$3!" set "$lf="
if defined $c set "$c==!$c!"
if defined $lf echo/!$b!!$c!
if "!$sn!"=="%~2" if "!$vf!"=="0" set $vf=1& echo !$3!=!$4!
for /f "tokens=1,2 delims=:" %%i in ("!$sn!:!$vf!") do (
ENDLOCAL& set "$sn=%%i"& set "$vf=%%j")))>"%$ft%"
copy /y "%$ft%" "%~1">nul&& del "%$ft%"
::----------------
ENDLOCAL& GoTo:EOF
> ByRef - префикс, обозначающий использование параметра по ссылке;
> очень странное имя для параметра... на всякий случай: оно не должно содержать символов ":" и "="
amel27, спасибо, теперь всё работает как надо.очень странное имя для параметра » Имелись ввиду ini-файлы "Оперы", а именно параметр standard_menu.ini: [Quick Preferences Menu]
Item, "Speed Dial - логотип вместо страницы" = Set preference,"User Prefs|Thumbnail Logo Score Logo URL=75" | Set preference,"User Prefs|Thumbnail Logo Score Logo URL=0" Скрипт задумывался как часть твика для установленной Opera 11.10.
Попробовал на реальном standard_menu.ini и обнаружилась новая проблема, связанная с кодировкой. Дело в том, что standard_menu.ini в кодировке UTF-8, и после отработки скрипта вместо русских букв получаем: Item, "Speed Dial - ⨯ ⢮ ⣠穢= и т.д. Хоть CMD-файл в OEM-866, ANSI-1251 - всё равно, а если для прикола сохранить в UTF-8 :) - скрипт такое с standard_menu.ini вытворяет, мама не горюй!:lol: Извиняюсь, может несколько не в эту тему, как в скрипте указать, что русские буквы должны находиться в UTF-8?
p.s. С кодировкой standard_menu.ini всё в порядке, скрипт её не меняет, если русские буквы не использовать - всё отрабатывает корректно!
BigBoo, возможно, Вам стоит перейти на использование WSH, а ещё лучше — PowerShell.
обнаружилась новая проблема, связанная с кодировкой »именно поэтому нужно сразу давать пример, максимально приближенный к "боевым" условиям, а не тот куцый, что из первого поста
а если для прикола сохранить в UTF-8 - скрипт такое с standard_menu.ini вытворяет, мама не горюй »на самом деле, если всё аккуратно сделать - убрать BOM и заэкранировать спецсимволы, то всё работает... просто в батнике в команде SET вместо русских букв будут "крякозябки", но ему по большому счету всё равно что менять... и понятное дело, учет регистра букв работать не будет
напрямую батник с UTF8 работать не может, так как для Windows "родными" являются OEM/ANSI/UTF-16 кодировки, но можно сделать предварительное преобразование в любую из этих кодировок, а после обработки вернуть в исходную (UTF8), вот пример для исходного файла UTF-8 with BOM (http://en.wikipedia.org/wiki/Byte_order_mark):
@echo off
set $par=Item, "Speed Dial - логотип вместо страницы"
set $val=Set preference,"User Prefs|Thumbnail Logo Score Logo URL=75" ^| Set preference,"User Prefs|Thumbnail Logo Score Logo URL=0"
CALL:INISET 1.txt paste $par $val
EXIT
:INISET %utf8_file_with_BOM% %section% parm val
::----------------------------------------------
SETLOCAL DisableDelayedExpansion
set $sn= & set "$t1=%TEMP%\%RANDOM%%RANDOM%.tmp"
set $vf=0& set "$t2=%TEMP%\%RANDOM%%RANDOM%.tmp"
chcp 65001|cmd/u/c Type "%~1">"%$t1%"&chcp 866>nul
(for /f "tokens=1* delims==]" %%a in ('type "%$t1%"^|find/n /v ""') do (set "$b=%%b"
SETLOCAL EnableDelayedExpansion
if "!$b:~0,1!"=="[" set "$sn=!$b:~1,-1!"
for /f "delims==" %%p in ("!$b!") do set "$p=%%p"
if /i not "!$sn!"=="%~2" (echo/!$b!) else (
if /i not "!$p!"=="!%~3!" if /i not "!$p!"=="!%~3! " echo/!$b!)
if "!$sn!"=="%~2" if "!$vf!"=="0" set $vf=1& echo/!%~3!=!%~4!
for /f "tokens=1,2 delims=:" %%i in ("!$sn!:!$vf!") do (
ENDLOCAL& set "$sn=%%i"& set "$vf=%%j"
)))>"%$t2%"
set/p $="я╗┐">"%$t1%"<nul
(for /f "usebackq delims=" %%a in ("%$t2%") do (set "$a=%%a"
CHCP 65001|cmd/v/c "echo/!$a!"&CHCP 866>nul))>>"%$t1%"
copy /y "%$t1%" "%~1">nul&& del "%$t1%"
::----------------
ENDLOCAL& GoTo:EOF
P.S. красным выделен BOM для UTF-8, лучше скопировать его с любого UTF8-текстовика
P.P.S. если исходный файл не содержит BOM, код придется изменить
красным выделен BOM для UTF-8, лучше скопировать его с любого UTF8-текстовика » Если честно, так и не понял. Что имеется ввиду под "скопировать BOM с любого UTF8-текстовика" и как это сделать?
И ещё вопрос: cmd-файл со скриптом в Вашем последнем примере сохраняется в OEM-866?
cmd-файл со скриптом в Вашем последнем примере сохраняется в OEM-866? »да
Что имеется ввиду под "скопировать BOM с любого UTF8-текстовика" и как это сделать? »
- создать в блокноте произвольный текст и сохранить его в файл в формате UTF-8;
- открыть полученный UTF8-файл в текстовом редакторе как DOS-текст (блокнот не поддерживает, я использую FAR);
- скопировать первые три спецсимвола (BOM) в отмеченное место батника;
P.S. Всё это имеет смысл только если обрабатываемые файлы Opera содержат BOM, в противном случае скрипт придется переделывать.
amel27, испробовал Ваш скрипт с учётом "BOM". Скрипт зацикливается на ошибке и далее иероглифы: Достигнут уровень рекурсии, максимально возможный для команды SETLOCAL. Если из INI-файла удалить всё, кроме нужной секции - отрабатывает, вставляя по одному символу в строку столбиком, где русские буквы - всё те же крякозябры.
Foreigner
21-04-2011, 22:42
BigBoo,
Мне кажется вы выбрали не тот инструмент, голые батники плохо работают с текстом, тем более в utf8, а если конфиг большой, то есть вероятность, что он его вообще не пропарсит. Если вы хотите твик оперы, то на мой взгляд, было бы проще и надежней просто заменить файл конфига другим, модифицированным.
проще и надежней просто заменить файл конфига другим, модифицированным » в принципе так я и делаю, просто интересно скриптом, чисто из познавательных соображений.
Если с CMD никак, будем думать о WSH.
Скрипт зацикливается на ошибке и далее иероглифы »не могу воспроизвести ошибку, выложите в архиве: INI-файл + сам батник
Мне кажется вы выбрали не тот инструмент.»это вопрос скорее философский, чем технический - так или иначе, с использованием "сторонних" решений или без них задачу можно решить любым инструментом... можно запускать NETSH из WSH и считать это чистым WSH-решением, с равным успехом можно задействовать WSH из батников, в конечном счете всё зависит от конкретной задачи и глубины её проработки
учитывая свойства INI-файла, я бы вообще не парился с правкой "середины текстового файла", а подошел с другой стороны:
- отфильтровать нужную строку через FIND/FINDSTR (вероятность того, что параметр встретится в другой секции =0);
- добавил в конец INI-файла кусок секции с одним нужным параметром;
- при запуске Opera автоматически сольёт все одноименные секции в одну.
это не решает вопроса с кодировкой, но снимает проблему парсинга содержимого
Foreigner
22-04-2011, 07:25
это вопрос скорее философский »
Я бы сказал, что это вопрос удобства. Писать портянку или использовать готовый нструмент:
@echo off
setlocal
set "file=Full\Path\To\file.ini"
:: Добавить или переписать параметр
nircmdc inisetval "%file%" "section 1" "key" "value"
nircmdc inisetval "%file%" "section 2" "testkey" "|^\><#@&&"
http://www.nirsoft.net/utils/nircmd.html
Главная беда с ini-файлами в том, что при переходе с Win3.x на Win9.x/WinNT почему-то, в эйфории, посчитали, что впредь ini-файлы будут не востребованы, и не добавили их встроенную поддержку ни в пакетные файлы, ни в Windows Script Host, ни, тем паче, в нынешний PowerShell.
nircmdc »UTF-8 без костылей не осилит, да и заявленный файл не похож на обычный INI,
с такими странными именами параметров nircmd его просто проигнорирует:Item, "Speed Dial - логотип вместо страницы" = ...
выложите в архиве: INI-файл + сам батник »
BigBoo, как и предполагал - INI-файлы не содержат BOM, если добавить - всё работает... предупреждал же:Всё это имеет смысл только если обрабатываемые файлы Opera содержат BOM, в противном случае скрипт придется переделывать »определитесь сначала с кодировкой исходных файлов... кстати, в моей Опере все INI с BOM
как и предполагал - INI-файлы не содержат BOM » Как же так, пользовался AkelPad - в строке состояния определяет: Win 65001 (UTF-8) *BOM!
Как же так »а проверить? ;)
...но мы ушли в сторону, вот пара тем (там есть и другие WSH/CMD варианты):
CMD/BAT - [решено] Автоматическая смена кодировки .txt файлов (http://forum.oszone.net/showthread.php?p=1157143)
CMD/BAT - [решено] Изменение кодировки txt файла из ANSI в UTF-16 LE (http://forum.oszone.net/showthread.php?p=1198191)
Foreigner
23-04-2011, 09:38
и не добавили их встроенную поддержку ни в пакетные файлы, ни в Windows Script Host, ни, тем паче, в нынешний PowerShell. »
Но по крайней мере в PowerShell гораздо проще работать с текстом. Вот пример:
$file = gc test.ini
$sections = @()
switch -regex ($file) {
"\[.*\]" {
$sec = @{}
$sec.name = $_
$sec.param = @()
$sec.value = @()
$sections += $sec
}
".*=.*" {
$sec.param += $($_ -replace '(.*)=.*', '$1')
$sec.value += $($_ -replace '.*=(.*)', '$1')
}
}
for ($i = 0; $i -le $($sections.count-1); $i++) {
$sections[$i].name
0..$($sections[$i].param.count-1) | % {
"$($sections[$i].param[$_]) = $($sections[$i].value[$_])"
}
}
Здесь просто выводится содержимое ini-файла, но не построчно, а как именованные свойства ini. Т.е. к любому из них можно обратиться не как к строке.
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.