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

batch script - find and replace line that starts with specific value in an .ini file

您好,首先我想为此道歉 post 如果之前已经回答过这个问题。我花了最后 4 个小时搜索 Whosebug 和 Google。

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

我试图更改的两行是:

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

我尝试了一些在 Whosebug 上找到的批处理脚本,但它们只有在我定义整行时才有效。由于每个用户都有不同的选项集,我需要脚本来开始行。例如 "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

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

但是这个文本文件 editing/replacing 任务仍然可以用 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 循环的解释,请参阅 上的答案。

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

另请查看有关 Windows Environment Variables 的维基百科文章。强烈建议为本地应用程序数据文件夹等文件夹路径使用正确的预定义环境变量。

要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • call /? ... 说明 %~n0 ... 没有路径和文件扩展名的批处理文件名。
  • del /?
  • echo /?
  • endlocal /?
  • fc /?
  • findstr /?
  • for /?
  • if /?
  • move /?
  • rem /?
  • set /?
  • 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 文件不存在的情况。