批量查找并替换括号之间的文本

时间:2020-09-16 08:11:44

标签: windows batch-file cmd

我需要用纯批处理的文本文件中的用户输入替换HOST = 之后的文本。 名称VM-TEST并不总是相同的,并且可以更改,因为它将在多个文件中使用。 我被困在这里。

文字示例:

(ADDRESS = (PROTOCOL = TCP)(HOST = VM-TEST)(PORT = 1521))

我只有这个:

@echo off &setlocal
set "search=host ="
set "replace=HOST = test"
set "textfile=Input.txt"
set "newfile=Output.txt"
(for /f "delims=" %%i in (%textfile%) do (
    set "line=%%i"
    setlocal enabledelayedexpansion
    set "line=!line:%search%=%replace%!"
    echo(!line!
    endlocal
))>"%newfile%"
del %textfile%
rename %newfile%  %textfile%

2 个答案:

答案 0 :(得分:0)

嘿:)我建立了一个小脚本,可以完成这项工作。 它将首先在左括号中分割属性,因此您可以检查其是否与要查找的属性匹配。这是使用findstr / r完成的,因此可以将简单的正则表达式编写为搜索字符串。您的名称“ VM-TEST”在正则表达式中表示为“。*”,因此可以是任何字符串。

@echo off & setlocal
set "search=host = .*)"
set "replace=HOST = test)"
set "textfile=in.txt"
set "newfile=out.txt"
del "%newfile%" 2>nul

for /f "usebackq delims=" %%L in ("%textfile%") do (
    call :replaceProperty "%%~L"
)

del "%textfile%"
rename "%newfile%" "%textfile%"
exit

:replaceProperty
set "_remainingLine=%~1"
set "_outputLine="

:replaceProperty_while
    if "%_remainingLine%"=="" goto break

    if "%_remainingLine:~0,1%"=="(" (
        rem this needs to be checked additionally as for /f skips empty tokens
        set "_outputLine=%_outputLine%("
        set "_remainingLine=%_remainingLine:~1%"
        goto replaceProperty_while
    )

    for /F "tokens=1* delims=(" %%q in ("%_remainingLine%") do (
        echo:%%q|findstr /i /r /c:"^%search%$">nul 
        if errorlevel 1 (
            set "_outputLine=%_outputLine%%%q"
        ) else (
            set "_outputLine=%_outputLine%%replace%"
        )

        if "%%r"=="" (
            goto break
        ) else (
            set "_remainingLine=(%%r"
        )
    )
goto replaceProperty_while

:break
    rem Finished processing the line. Write output and exit subroutine.
    rem This can't be done in the if-block because the output line will contain brackets.
    echo:%_outputLine%>>"%newfile%"
exit /b

这是我用于测试的示例文件:

(ADDRESS = (PROTOCOL = TCP)(HOST = VM-TEST)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = Something_else)(PORT = 1521))
this line won't get modified
(this works as well but
trailing brackets will get lost though (
((some other stuff = (text) ))
((HOST = VM-TEST)(PORT = 1521)(PROTOCOL = TCP))

编辑#1,2:更新了代码,以提供领先的空白支持和性能改进。

编辑#3:我假设文件中的每一行至少包含一个空格,但是如果您希望不丢失空行,则可以用以下内容替换第一个for /f "usebackq ...循环:< / p>

for /f "tokens=1* delims=:" %%K in ('findstr /n /r "^" "%textfile%"') do (
    call :replaceProperty "%%~L"
)

答案 1 :(得分:0)

您可以尝试以下脚本:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_ROOT=D:\Target" & rem // (path to target directory)
set "_IFILE=Input.txt" & rem // (name of input file)
set "_OFILE=Output.txt" & rem // (name of output file)
set "_SEARCH=HOST" & rem // (keyword to search for)
set /P _REPLAC="Enter new HOST value: " & rem // (replacement value)

rem // Gather horizontal tabulator (TAB) character:
for /F "delims=" %%T in ('forfiles /P "%~dp0." /M "%~nx0" /C "cmd /C echo/0x09"') do set "_TAB=%%T"

rem // Write to output file:
> "%_ROOT%\%_OFILE%" (
    rem /* Read from input file line by line, precede each line with line number + `:`
    rem    in order not to appear empty to `for /F` and therefore not to be skipped: */
    for /F "delims=" %%L in ('findstr /N "^" "%_ROOT%\%_IFILE%"') do (
        rem // Store current line, reset line buffer:
        set "LINE=%%L" & set "COLL=("
        rem // Toggle delayed expansion to avoid trouble with `!`:
        setlocal EnableDelayedExpansion
        rem // Remove temporary line number + `:` prefix:
        set "LINE=!LINE:*:=!"
        rem // Skip processing of an empty line:
        if defined LINE (
            rem // Skip processing of a line that contains `*`, `?`, `<`, `>`:
            if "!LINE!"=="!LINE:**=!" if "!LINE!"=="!LINE:*?=!" if "!LINE!"=="!LINE:*<=!" if "!LINE!"=="!LINE:*>=!" (
                rem // Temporarily double `"`:
                set "LINE=!LINE:"=""!^"
                rem // Split line at every `(` and loop through the items:
                for %%I in ("!LINE:(=" "!") do (
                    endlocal
                    rem // Store current item:
                    set "ITEM=%%~I"
                    rem // Split item into keyword and remainder:
                    for /F "tokens=1* delims==%_TAB% " %%G in ("%%~I") do (
                        rem // Check whether keyword matches:
                        if /I "%%G"=="%_SEARCH%" (
                            rem // Split off `)` and everything behind from remainder:
                            set "REST=%%H"
                            setlocal EnableDelayedExpansion
                            for /F "tokens=1* delims=)" %%E in ("!REST:)=)(!") do (
                                endlocal
                                rem // Rebuild new item with replacement value:
                                set "ITEM=%%G = %_REPLAC%)%%F"
                                setlocal EnableDelayedExpansion
                            )
                            endlocal
                        )
                    )
                    setlocal EnableDelayedExpansion
                    rem // Revert doubling `"`:
                    if defined ITEM set "ITEM=!ITEM:""="!^"
                    rem /* Append item to line buffer;
                    rem    transport result beyond `endlocal`: */
                    if defined ITEM set "ITEM=!ITEM:(=!"
                    for /F "delims=" %%K in ("!COLL!(!ITEM!") do (
                        endlocal
                        set "COLL=%%K"
                        setlocal EnableDelayedExpansion
                    )
                )
                set "LINE=!COLL:~2!"
            )
        )
        rem // Return resulting line:
        echo(!LINE!
        endlocal
    )
)

endlocal
exit /B

以下限制适用:

  • 要搜索的关键字不能包含= SPACE TAB ()
  • 要敏感地区分给定要搜索的关键字(例如HOST)((要进行更改,请从/I中删除if /I "%%G"=="%_SEARCH%"选项);
  • 包含要搜索关键字的
  • 行(例如HOST)不得包含任何字符*?<>;如果这样做,则无法执行所需的替换;
  • 在被替换的字符串部分(例如=)中,HOST = VM-TEST-符号周围的空格的原始顺序未得到维护,它始终是关键字+ SPACE + = + 空格 +替换值;
相关问题