如何在批处理文件中查找并使用通配符替换字符串?

时间:2019-06-24 21:26:47

标签: batch-file replace

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

我已经可以将findstrwildcard一起使用,但是我无法对输出使用某种替换。我还找到了一些可以使用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,这是我需要服务使用的端口。 / p>

3 个答案:

答案 0 :(得分:0)

我决定走另一条路,并调用powershell,而不是尝试将所有这些工作都保存在bat文件中。

(Get-Content C:\Users\David\Desktop\streamstack.exe.config) | ForEach-Object { $_ - 
replace "http://localhost:.*/", "http://localhost:80/" } | Set-Content 
c:\blah\blah\streamstack.exe.config

这似乎可以完成工作,并且我可以使用...从蝙蝠内执行它。

powershell -executionPolicy bypass -noexit -file 

答案 1 :(得分:0)

您尚未提供有关配置文件格式的任何详细信息。

假设每行有一个名称/值设置,并且行的顺序 无关紧要,那么有一个非常简单的批处理解决方案高效。使用FINDSTR将所有行 写入本地主机行,然后追加所需的本地主机行。

>"%target%" (findstr /v "^http://localhost:" "%source%" & echo http://localhost:80)

当然,如果行的顺序很重要,则上述方法将无效。

您应该查看我的JREPL.BAT regular expression find/replace utility。它非常强大,但易于使用。它是纯脚本(混合批处理/ JScript),可从XP开始在任何Windows计算机上运行。

使用与在PowerShell中使用的相同的查找/替换,JREPL解决方案将是

call jrepl "(http://localhost):.*" "$1:80" /f "%source%" /o "%target%"

我使用了一个正则表达式捕获组来节省一些打字。

JREPL有很多选项,并且该实用程序内置了完整的文档。使用jrepl /?help获取所有可用帮助类型的描述。

答案 2 :(得分:0)

由于您尝试替换URL中的端口号,因此我对搜索字符串进行了一些扩展,以便在协议定义://http之后以及之前添加前导https主机名以及端口号后的/(也符合your own answer)。

以下脚本仅在第一次出现所需的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