首页 > 解决方案 > 如何在批处理文件中查找和替换带有通配符的字符串?

问题描述

我对这一切都很陌生,所以请放轻松。我正在尝试使我更改特定服务的端口的过程自动化。端口在文件 streamstack.exe.config 中确定。我有一些东西可以找到并替换文件中的特定字符串,但是在某些情况下我不知道定义的端口号。是否可以找到包含通配符的字符串并替换为预定义的字符串?例如查找"localhost:.*"并替换为"localhost:80"?

我已经能够使用findstra wildcard,但是我无法对输出使用某种替换。我还找到了可以使用 找到替换的东西setlocal enabledelayedexpansion,但是我不知道如何使用通配符。

我的代码是:

@echo off

set "replace=localhost:.*"
set "replaced=localhost:80"

set "source=c:\blah\blah\streamstack.exe.config"
set "target=c:\blah\blah\streamstack1.exe.config"


setlocal enableDelayedExpansion
(
   for /f "tokens=1* delims=:" %%a in ('findstr /N "^" %source%') do (
      set "line=%%b"
      if defined line set "line=!line:%replace%=%replaced%!"
      echo(!line!
   )
) > %target%
endlocal

我希望它能够找到包含localhost:后跟代表端口的任何数字组的字符串,并替换为localhost:80,这是我需要服务使用的端口。

标签: batch-filereplace

解决方案


由于您尝试替换 URL 中的端口号,因此我稍微扩展了搜索字符串,以便://在协议定义之后httphttps主机名之前包含前导,以及/端口号之后的尾随(这也符合您自己的回答)。

以下脚本仅在所需 URL 的第一次出现时替换端口号,当遇到像://plus 给定主机名 plus:加上纯数字端口号 plus这样的字符串时会找到该 URL /

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_SOURCE=c:\blah\blah\streamstack.exe.config" & rem // (original file)
set "_TARGET=c:\blah\blah\streamstack.exe.config" & rem // (modified file)
set "_TEMP=%TEMP%\%~n0_%RANDOM%.tmp"              & rem // (temporary file)
set "_HOST=localhost"                             & rem // (host name)
set "_PORT=80"                                    & rem // (new port name)

rem // Define to write to console if no target file is given:
if not defined _TARGET set "_TEMP=con"

rem // Store line-feed in variable:
(set ^"_LF=^
%= blank line =%
^")

rem // Write output to temporary file:
> "%_TEMP%" (
    rem // Read source file line by line, precede each line by line number plus `:`:
    for /F "delims=" %%L in ('findstr /N "^" "%_SOURCE%"') do (
        rem // Store currently iterated line, reset buffer for part left to host name:
        set "LINE=%%L" & set "LEFT="
        rem // Toggle delayed expansion to avoid trouble with exclamation marks:
        setlocal EnableDelayedExpansion
        rem // Get line portion right to `://` + host name + `:`:
        set "RIGHT=!LINE:*://%_HOST%:=!"
        rem // Check whether host name part has really been found:
        if not "!LINE!" == "!RIGHT!" (
            rem /* Buffer right line portion in a `for` variable
            rem    to transport it over the `endlocal` barrier: */
            for /F "delims=" %%J in (^""!RIGHT!"^") do (
                rem // Replace `://` + host name + `:` by a line-feed:
                for /F "delims=" %%I in (^"!LINE:://%_HOST%:^=^%_LF%%_LF%!^") do (
                    rem /* Ensure to only process first line of multi-line string
                    rem    to get the line portion left to `://`+ host name + `:`: */
                    if not defined LEFT (
                        endlocal
                        rem /* Store line portion left to `://` + host name + `:`,
                        rem    restore right line portion from `for` variable: */
                        set "LEFT=%%I" & set "RIGHT=%%~J"
                        rem /* Split off everything behind the first `/`, which
                        rem    constitutes the port number: */
                        for /F "delims=/" %%F in ("0%%~J") do (
                            rem /* Check whether port number is purely numeric;
                            rem    this is done by checking whether a `for /F` loop
                            rem    iterates if numerals are defined as delimiters: */
                            for /F "delims=0123456789" %%E in ("%%F") do rem/
                        ) && (
                            rem // `for /F` loop iterated, hence keep current line:
                            setlocal EnableDelayedExpansion
                        ) || (
                            rem // `for /F` loop did not iterate, change port number:
                            setlocal EnableDelayedExpansion
                            set "LINE=!LEFT!://%_HOST%:%_PORT%/!RIGHT:*/=!"
                        )
                    )
                )
            )
        )
        rem // Return line string:
        echo(!LINE:*:=!
        endlocal
    )
)
rem /* Move temporary file onto target file;
rem    this allows source and target files to be identical: */
if defined _TARGET > nul move /Y "%_TEMP%" "%_TARGET%"

endlocal
exit /B

推荐阅读