batch-file - 如何在批处理文件中查找和替换带有通配符的字符串?
问题描述
我对这一切都很陌生,所以请放轻松。我正在尝试使我更改特定服务的端口的过程自动化。端口在文件 streamstack.exe.config 中确定。我有一些东西可以找到并替换文件中的特定字符串,但是在某些情况下我不知道定义的端口号。是否可以找到包含通配符的字符串并替换为预定义的字符串?例如查找"localhost:.*"
并替换为"localhost:80"
?
我已经能够使用findstr
a 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
,这是我需要服务使用的端口。
解决方案
由于您尝试替换 URL 中的端口号,因此我稍微扩展了搜索字符串,以便://
在协议定义之后http
或https
主机名之前包含前导,以及/
端口号之后的尾随(这也符合您自己的回答)。
以下脚本仅在所需 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
推荐阅读
- google-apps-script - 获取所有数据范围
- json - 使用名为 self 的元素解码 JSON
- spring-boot - Spring 5 Security:'没有为 id null 映射的密码编码器'
- gitlab - GitLab CE 在哪里显示提交状态?
- python - TypeError:“int”对象在 np.random.seed 中不可调用
- python - Lustre 文件系统上有多个读取器的 SQLite“磁盘 I/O 错误”
- python - 如何计算 Python 中包括结尾新行在内的行数?
- python - Nornir:将 Python 函数传递给 Jinja2 模板
- loops - Haskell中的双重for循环
- javascript - 调用一个正在获取 API 并呈现返回值的函数,Promises 的问题