批处理脚本-查找并替换以.ini文件中的特定值开头的行

时间:2018-10-09 01:17:34

标签: batch-file scripting ini

您好,首先,我想对这篇帖子表示歉意,如果以前已经回答过的话。我花了最后4个小时来搜索Stackoverflow和Google。

我有一个gamesettings.ini文件,我想通过批处理文件进行编辑。我需要在许多PC上执行此操作,因此我希望保留文件中除2行之外的其他设置。

我要更改的两行是:

CustomVoiceChatInputDevice =默认输入
CustomVoiceChatOutputDevice =默认输出

我尝试了一些在Stackoverflow上找到的批处理脚本,但是只有在定义完整行时它们才起作用。由于每个用户都有不同的选项集,因此我需要脚本来开始这一行。例如“ CustomVoiceChatInputDevice”。

这是我使用的示例代码,这要感谢@jsanchez。除非我输入整行,否则该脚本将不起作用:

谢谢您的时间!

@echo off
::Use the path from whence the script was executed as
::the Current Working Directory
set CWD=C:\

::***BEGIN MODIFY BLOCK***
::The variables below should be modified to the
::files to be changed and the strings to find/replace
::Include trailing backslash in _FilePath
set _FilePath=C:\Users\NEOSTORM\AppData\Local\RedDeadGame\Saved\Config\WindowsClient\
set _FileName=GameUserSettings.ini
::_WrkFile is the file on which the script will make
::modifications.
set _WrkFile=GameUserSettings.bak
set OldStr="CustomVoiceChatInputDevice"
set NewStr="CustomVoiceChatInputDevice=Line (Astro MixAmp Pro Game)"

::***END MODIFY BLOCK***

::Set a variable which is used by the
::search and replace section to let us
::know if the string to be modified was
::found or not.
set _Found=Not found

SETLOCAL
SETLOCAL ENABLEDELAYEDEXPANSION

if not exist "%_FilePath%%_FileName%" goto :NotFound

::If a backup file exists, delete it
if exist "%_FilePath%%_WrkFile%" (
    echo Deleting "%_FilePath%%_WrkFile%" 
    del "%_FilePath%%_WrkFile%" >nul 2>&1
    )

echo.
echo Backing up "%_FilePath%%_FileName%"...
copy "%_FilePath%%_FileName%" "%_FilePath%%_WrkFile%" /v

::Delete the original file. No worries, we got a backup.
if exist "%_FilePath%%_FileName%" del "%_FilePath%%_FileName%"
echo.
echo Searching for %OldStr% string...
echo.
for /f "usebackq tokens=*" %%a in ("%_FilePath%%_WrkFile%") do (
    set _LineChk=%%a
    if "!_LineChk!"==%OldStr% (
        SET _Found=Found 
        SET NewStr=!NewStr:^"=! 
        echo !NewStr!
        ) else (echo %%a)
        )>>"%_FilePath%%_FileName%" 2>&1

::If we didn't find the string, rename the backup file to the original file name
::Otherwise, delete the _WorkFile as we re-created the original file when the
::string was found and replaced.
if /i "!_Found!"=="Not found" (echo !_Found! && del "%_FilePath%%_FileName%" && ren "%_FilePath%%_WrkFile%" %_FileName%) else (echo !_Found! && del "%_FilePath%%_WrkFile%")
goto :exit

:NotFound
echo.
echo File "%_FilePath%%_FileName%" missing. 
echo Cannot continue...
echo.
:: Pause script for approx. 10 seconds...
PING 127.0.0.1 -n 11 > NUL 2>&1
goto :Exit

:Exit
exit /b

2 个答案:

答案 0 :(得分:2)

.ini文件中的每个设置都标识该设置的名称。因此,行的顺序不应可能无关紧要。

如果 行顺序没有意义,那么您所需要做的就是使用FINDSTR / V删除旧值,然后简单地附加新值。在下面的脚本中,我同时修改了两个值。

@echo off
setlocal enableDelayedExpansion

set "iniLoc=C:\Users\NEOSTORM\AppData\Local\RedDeadGame\Saved\Config\WindowsClient"
set "iniFile=%iniLoc%\GameUserSettings.ini"
set "iniBackup=%iniLoc%\GameUserSettings.bak"
set "CustomVoiceChatInputDevice=Line (Astro MixAmp Pro Game)"
set "CustomVoiceChatOutputDevice=Some new value"

>"%iniFile%.new" (
  findstr /vb "CustomVoiceChatInputDevice= CustomVoiceChatOutputDevice=" "%iniFile%"
  echo CustomVoiceChatInputDevice=!CustomVoiceChatInputDevice!
  echo CustomVoiceChatOutputDevice=!CustomVoiceChatOutputDevice!
)
copy "%iniFile%" "%iniBackup%"
ren "%iniFile%.new" *.

通过重命名而不是通过副本创建备份文件会稍快一些,但是稍后会出现ini文件不存在的瞬间。

答案 1 :(得分:0)

Windows命令处理器不适用于编辑文本文件,而设计用于运行命令和应用程序。

但是仍然可以使用cmd.exe(非常慢)完成此文本文件编辑/替换任务:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FileName=%LOCALAPPDATA%\RedDeadGame\Saved\Config\WindowsClient\GameUserSettings.ini"
set "TempFile=%TEMP%\%~n0.tmp"
if not exist "%FileName%" goto EndBatch

del "%TempFile%" 2>nul

for /F delims^=^ eol^= %%A in ('%SystemRoot%\System32\findstr.exe /N "^" "%FileName%"') do (
    set "Line=%%A"
    setlocal EnableDelayedExpansion
    if not "!Line:CustomVoiceChatInputDevice=!" == "!Line!" (
        echo CustomVoiceChatInputDevice=Line (Astro MixAmp Pro Game^)
    ) else if not "!Line:CustomVoiceChatOutputDevice=!" == "!Line!" (
        echo CustomVoiceChatOutputDevice=Line (Astro MixAmp Pro Game^)
    ) else echo(!Line:*:=!
    endlocal
) >>"%TempFile%"

rem Is the temporary file not binary equal the existing INI file, then move
rem the temporary file over existing INI file and delete the temporary file
rem if that fails like on INI file currently opened by an application with
rem no shared write access. Delete the temporary file if it is binary equal
rem the existing INI file because of nothing really changed.

%SystemRoot%\System32\fc.exe /B "%TempFile%" "%FileName%" >nul
if errorlevel 1 (
    move /Y "%TempFile%" "%FileName%"
    if errorlevel 1 del "%TempFile%"
) else del "%TempFile%"

:EndBatch
endlocal

有关{strong> FOR 循环的说明,请参见How to read and print contents of text file line by line?上的答案。

请注意要输出的两行中^左侧的插入符号)。双引号参数字符串之外的右括号必须在此处用^进行转义,否则)将被Windows命令处理器解释为命令块的末尾,而不是由命令输出的文字字符回声 ECHO 命令行上的cmd.exe也必须使用&|<>来转义在解析命令行或整个命令块(如^时对call /?具有特殊含义的其他字符。 / p>

另请参阅Wikipedia上有关Windows Environment Variables的文章。强烈建议对文件夹路径(例如本地应用程序数据文件夹)使用正确的预定义环境变量。

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • %~n0 ...说明del /? ...批处理文件名,不包含路径和文件扩展名。
  • echo /?
  • endlocal /?
  • fc /?
  • findstr /?
  • for /?
  • if /?
  • move /?
  • rem /?
  • set /?
  • setlocal /?
  • import re pat = re.compile(".*\/\d{3}\/\d{2}\/\d{4}\.format") if pat.match(item): # Your code here