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

Batch file 批处理脚本-在.ini文件中查找并替换以特定值开头的行,batch-file,scripting,ini,Batch File,Scripting,Ini,您好,首先我想为这篇文章道歉,如果它之前已经被回复了。我花了4个小时搜索Stackoverflow和Google 我有一个gamesettings.ini文件,我想通过批处理文件进行编辑。我需要在许多电脑上执行此操作,因此我希望保留文件中除2行之外的其他设置 我试图改变的两行是: CustomVoiceChatInputDevice=默认输入 CustomVoiceChatOutputDevice=默认输出 我尝试了在Stackoverflow上找到的一些批处理脚本,但它们只有在我定义完整行时才

您好,首先我想为这篇文章道歉,如果它之前已经被回复了。我花了4个小时搜索Stackoverflow和Google

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

我试图改变的两行是:

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

我尝试了在Stackoverflow上找到的一些批处理脚本,但它们只有在我定义完整行时才起作用。因为每个用户都有不同的选项集,所以我需要脚本来作为行的开始。例如,只需定制VoiceChatInputDevice

感谢@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

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
有关for循环的说明,请参见上的答案

请注意要输出的两行中的插入符号“^left to”。双引号参数字符串外的右括号必须在此处用^转义,否则Windows命令处理器会将其解释为命令块的结尾,而不是命令回显输出的文字字符。在分析命令行或整个命令块时,对cmd.exe具有特殊意义的其他字符(如&|)也必须在ECHO命令行中用“^”转义

请看一看维基百科上关于这个问题的文章。强烈建议对文件夹路径(如本地应用程序数据文件夹)使用正确的预定义环境变量

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

呼叫/。。。解释%n0。。。批处理文件名,不带路径和文件扩展名。 德尔/? 回声/? endlocal/? fc/? findstr/? 对于/? 如果/? 移动/? 雷姆/? 集/? setlocal/?
.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文件不存在。

大多数*.ini文件都包含节,即[节名]在这种情况下,文件中以CustomVoiceChatInputDevice=和CustomVoiceChatOutputDevice=开头的行的位置很重要。不幸的是,原始海报并没有写任何关于INI文件内容的内容来修改。@Mofi-没有什么好的理由,我想象着OP开发的一款国产游戏,并想象着顺序无关紧要。但是你提出了一个很好的观点,这更可能是一个商业游戏,在这个游戏中,线路顺序可能很重要。谢谢@mofi!!这真的很有效!你是上帝: