【问题标题】:batch script - find and replace line that starts with specific value in an .ini file批处理脚本 - 查找并替换 .ini 文件中以特定值开头的行
【发布时间】:2019-03-13 16:51:03
【问题描述】:

您好,首先我想为这篇文章道歉,如果它之前已经回答过。我花了最后 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

【问题讨论】:

    标签: batch-file scripting ini


    【解决方案1】:

    .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 文件都包含部分,即[Section Name],在这种情况下,以CustomVoiceChatInputDevice=CustomVoiceChatOutputDevice= 开头的行在文件中的位置很重要。不幸的是,原始海报没有写任何关于INI文件内容的修改。
    • @Mofi - 无缘无故地,我设想的是 OP 开发的本土游戏,并认为顺序无关紧要。但你提出了一个很好的观点,它更有可能是一个商业游戏,线路顺序可能很重要。
    【解决方案2】:

    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 循环的说明,请参阅How to read and print contents of text file line by line? 上的答案。

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

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

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

    • call /? ... 解释%~n0 ... 批处理文件名,不带路径和文件扩展名。
    • del /?
    • echo /?
    • endlocal /?
    • fc /?
    • findstr /?
    • for /?
    • if /?
    • move /?
    • rem /?
    • set /?
    • setlocal /?

    【讨论】:

    • 谢谢@mofi !!这真的很好用!你是神:)
    猜你喜欢
    • 2016-04-26
    • 2016-01-18
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    相关资源
    最近更新 更多