除了SED之外,等号还可以怎样替换呢? 如何在字符串替换中使用字符串变量?
考虑这个例子:
For /F "tokens=*" %%B IN (test.txt) DO (
SETLOCAL ENABLEDELAYEDEXPANSION
SET t=is
SET old=%%B
SET new=!old:t=!
ECHO !new!
ENDLOCAL
)
:: SET new=!old:==!
两个问题:
首先,我不能在 !:=! 中使用变量 %t%。
SET t=is
SET old=%%B
SET new=!old:t=!
第二,我无法替换命令行中的等号
SET new=!old:==!
我自己刚刚为此创建了一个简单的解决方案,也许它对某人有帮助。
缺点(或优点,取决于你想要做什么)是,多个等号一个接一个地被像一个单个等号一样处理。 (例如:“str==ing”给出与“str=ing”相同的输出)
@echo off
set "x=this is=an test="
echo x=%x%
call :replaceEqualSign in x with _
echo x=%x%
pause&exit
:replaceEqualSign in <variable> with <newString>
setlocal enableDelayedExpansion
set "_s=!%~2!#"
set "_r="
:_replaceEqualSign
for /F "tokens=1* delims==" %%A in ("%_s%") do (
if not defined _r ( set "_r=%%A" ) else ( set "_r=%_r%%~4%%A" )
set "_s=%%B"
)
if defined _s goto _replaceEqualSign
endlocal&set "%~2=%_r:~0,-1%"
exit /B
如您所见,您可以像这样使用该函数:
call :replaceEqualSign in variableName with newString
应将
setlocal enableDelayedExpansion
移至旧的=%%B 分配之后,以防 %%B 包含 !
。
“t”问题很容易通过使用另一个 FOR 变量在循环内解决
For /F "tokens=*" %%B IN (test.txt) DO (
SET t=is
SET old=%%B
SETLOCAL ENABLEDELAYEDEXPANSION
for /f %%T in ("!t!") do SET new=!old:%%T=!
ECHO !new!
ENDLOCAL
)
没有简单的原生批处理解决方案可以替代
=
。您可以逐个字符地迭代字符串,但这很慢。您最好的选择可能是切换到 VBScript 或 JScript,或使用非本机实用程序。
如果您确实想使用纯 Windows 批处理命令来执行此操作,可以在 http://www.dostips.com/forum/viewtopic.php?t=1485
找到一些有趣的想法更新2:该实现被更可靠的实现所取代:https://github.com/andry81/contools/tree/HEAD/Scripts/Tools/std/encode/
替换等号:
@echo off
setlocal DISABLEDELAYEDEXPANSION
set __STRING__=1=2=3
call encode_dollar_char.bat
call encode_equal_char.bat
setlocal ENABLEDELAYEDEXPANSION & for /F "eol= tokens=* delims=" %%i in ("!__STRING__:$3D=!") do endlocal & set "__STRING__=%%i"
call decode_dollar_char.bat
set __STRING__
rem To return the variable outside the script (the delayed expansion must be disable outside the script, otheriwise the `!` character will be expanded):
setlocal ENABLEDELAYEDEXPANSION & for /F "eol= tokens=* delims=" %%i in ("!__STRING__!") do endlocal & endlocal & set "__STRING__=%%i"
setlocal ENABLEDELAYEDEXPANSION & for /F "eol= tokens=* delims=" %%i in ("!__STRING__!") do endlocal & endlocal & set "__STRING__=%%i"
__STRING__=123
更新:最新版本在这里:https://github.com/andry81/contools(https://github.com/andry81/contools/tree/HEAD/Scripts/Tools/std/)
您可以使用一些序列来临时用占位符替换特殊字符,例如 ?00、?01、?02 和 ?03。我基本上使用这组脚本:
替换_sys_chars.bat:
@echo off
rem Description:
rem Script to replace ?, !, %, and = characters in variables by respective
rem ?00, ?01, ?02 and ?03 placeholders.
setlocal DISABLEDELAYEDEXPANSION
set "__VAR__=%~1"
if "%__VAR__%" == "" exit /b 1
rem ignore empty variables
call set "STR=%%%__VAR__%%%"
if "%STR%" == "" exit /b 0
set ?01=!
call set "STR=%%%__VAR__%:?=?00%%"
set "STR=%STR:!=?01%"
setlocal ENABLEDELAYEDEXPANSION
set STR=!STR:%%=?02!
set "STR_TMP="
set INDEX=1
:EQUAL_CHAR_REPLACE_LOOP
set "STR_TMP2="
for /F "tokens=%INDEX% delims== eol=" %%i in ("/!STR!/") do set STR_TMP2=%%i
if "!STR_TMP2!" == "" goto EQUAL_CHAR_REPLACE_LOOP_END
set "STR_TMP=!STR_TMP!!STR_TMP2!?03"
set /A INDEX+=1
goto EQUAL_CHAR_REPLACE_LOOP
:EQUAL_CHAR_REPLACE_LOOP_END
if not "!STR_TMP!" == "" set STR=!STR_TMP:~1,-4!
(
endlocal
endlocal
set "%__VAR__%=%STR%"
)
exit /b 0
restore_sys_chars.bat:
@echo off
rem Description:
rem Script to restore ?, !, %, and = characters in variables from respective
rem ?00, ?01, ?02 and ?03 placeholders.
setlocal DISABLEDELAYEDEXPANSION
set "__VAR__=%~1"
if "%__VAR__%" == "" exit /b 1
rem ignore empty variables
call set "STR=%%%__VAR__%%%"
if "%STR%" == "" exit /b 0
setlocal ENABLEDELAYEDEXPANSION
set STR=!STR:?02=%%!
set STR=!STR:?03==!
(
endlocal
set "STR=%STR%"
)
set "STR=%STR:?01=!%"
set "STR=%STR:?00=?%"
(
endlocal
set "%__VAR__%=%STR%"
)
exit /b 0
示例:
@echo off
setlocal DISABLEDELAYEDEXPANSION
for /F "usebackq tokens=* delims=" %%i in ("test.txt") do (
set VALUE=%%i
call :PROCESS
)
exit /b 0
:PROCESS
if "%VALUE%" == "" exit /b 0
set "VALUE_=%VALUE%"
call replace_sys_chars.bat VALUE_
rem do variable arithmetic here as usual
if not "%VALUE_:?00=%" == "%VALUE_%" echo."%VALUE%" having ?
if not "%VALUE_:?01=%" == "%VALUE_%" echo."%VALUE%" having !
if not "%VALUE_:?02=%" == "%VALUE_%" echo."%VALUE%" having %%
if not "%VALUE_:?03=%" == "%VALUE_%" echo."%VALUE%" having =
rem restore it
call restore_sys_chars.bat VALUE_
echo "VALUE=%VALUE_%"
echo.---
测试.txt:
111/222
AAA=BBB
CCC=%DDD%
EEE=!FFF!
FFF=?00?01?02?03
结果:
"VALUE=111/222"
---
"AAA=BBB" having =
"VALUE=AAA=BBB"
---
"CCC=%DDD%" having %
"CCC=%DDD%" having =
"VALUE=CCC=%DDD%"
---
"EEE=!FFF!" having !
"EEE=!FFF!" having =
"VALUE=EEE=!FFF!"
---
"FFF=?00?01?02?03" having ?
"FFF=?00?01?02?03" having =
"VALUE=FFF=?00?01?02?03"
---
特点:
为什么不使用Edlin?我找不到一种方法来用一个初始文件来做到这一点,并且 Edlin 没有错误,但只需使用 NUL: 忽略它们。 奇怪的是,即使 = 和 ! 之间有文件结束符, TYPE %0 也包含整个文件,运行后在批处理文件上使用 TYPE 将不会以相同的方式工作。
@ECHO OFF
GOTO skip
1,1r=!
e
:skip
SET "new==old============="
ECHO %new% > %TEMP%\var.tmp
TYPE %0 > %TEMP%\edlin.tmp
EDLIN %TEMP%\var.tmp < %TEMP%\edlin.tmp > NUL:
SET /P newnew=<%TEMP%\VAR.TMP
ECHO %newnew%
ERASE %TEMP%\VAR.TMP
ERASE %TEMP%\VAR.BAK
ERASE %TEMP%\edlin.tmp
我正在研究这个,因为我需要去掉像“test=goingon”这样的字符串中的 = 我发现使用 test=goingon 作为参数调用下一个批处理文件,在该批处理文件中我有参数 1,“test”和 2,“goingon”。
所以: 批处理文件 1:
@echo off
call test2.bat test=goingon
批处理文件2:
echo arg1: %1
echo arg2: %2
结果:
arg1: test
arg2: goingon
我利用了 Bosj 的想法来想出这个。它有效。
set s=Abra=Cadabra
echo now you see it %s%
call :ReplaceEqual %s%
echo now you don't %s%
exit /b
:ReplaceEqual
set s=%1_%2
exit /b
我在另一篇文章中的回答,但它也适用于这里:
有一个更简单的替代方案。不要传入包含等号的值,而是尝试使用冒号之类的值。然后,通过修改该值(冒号)的能力,您可以将其转换回等于。这是一个例子:
@echo off
set VALUE1=%1
set VALUE2=%VALUE1::==%
echo value1 = %VALUE1%
echo value2 = %VALUE2%
运行批处理文件时,这样调用它:
C:\>myBatch name:someValue
输出将是:
value1 = name:someValue
value2 = name=someValue
如果名称或值包含空格,您将需要解决其他问题。您需要将整个字符串用双引号引起来。但是,你就会遇到需要摆脱它们的问题。这也可以处理,像这样:
@echo off
cls
set PARAM=%1
set BASE=%PARAM:"=%
set PAIR=%BASE::==%
rem Either of these two lines will do the same thing - just notice the 'delims'
rem for /f "tokens=1,2 delims=:" %%a in ("%BASE%") do set NAME=%%a & set VALUE=%%b
rem for /f "tokens=1,2 delims==" %%a in ("%PAIR%") do set NAME=%%a & set VALUE=%%b
for /f "tokens=1,2 delims=:" %%a in ("%BASE%") do set NAME=%%a & set VALUE=%%b
echo param = %PARAM%
echo base = %BASE%
echo pair = %PAIR%
echo name = %NAME%
echo value = %VALUE%
像这样运行这个批处理文件时:
C:\>myBatch "some name:another value"
输出将是:
param = "some name:another value"
base = some name:another value
pair = some name=another value
name = some name
value = another value
希望能帮助其他人通过批处理文件赢得战斗。
迈克五世