简体   繁体   English

批处理文件:如何替换“=”(等号)和字符串变量?

[英]Batch file: How to replace “=” (equal signs) and a string variable?

Besides SED, how can an equal sign be replaced? 除了SED,如何更换等号? And how can I use a string variable in string replacement? 如何在字符串替换中使用字符串变量?

Consider this example: 考虑这个例子:

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:==!

Two problems: 两个问题:

First, I cannot use the variable %t% in !:=!. 首先,我不能在!:=!中使用变量%t%。

   SET t=is
   SET old=%%B
   SET new=!old:t=!

Second, I cannot replace the equal sign in the command line 其次,我无法替换命令行中的等号

   SET new=!old:==!

I just created a simple solution for this myself, maybe it helps someone. 我刚刚为此创建了一个简单的解决方案,也许它可以帮到某个人。

The disadvantage (or advantage, depends on what you want to do) is that multiple equal signs one after another get handled like one single equal sign. 缺点(或优势,取决于你想要做什么)是一个接一个地处理多个等号,就像一个单一的等号。 (example: "str==ing" gives the same output as "str=ing") (例如:“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

As you have seen, you use the function like this: 如您所见,您使用如下函数:

call :replaceEqualSign in variableName with newString

The setlocal enableDelayedExpansion should be moved after your old=%%B assignment in case %%B contains ! 如果%% B包含旧的= %% B分配,则应移动setlocal enableDelayedExpansion ! .

The "t" problem is easy to solve within a loop by using another FOR variable 通过使用另一个FOR变量,“t”问题很容易在循环内解决

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
)

There is no simple native batch solution for replacing = . 替换=没有简单的本地批处理解决方案。 You can iterate through the string, character by character, but that is slow. 你可以逐个字符地遍历字符串,但这很慢。 Your best bet is probably to switch to VBScript or JScript, or use a non-native utility. 您最好的选择可能是切换到VBScript或JScript,或使用非本机实用程序。

If you really want to do this using pure Windows batch commands, there are a couple of interesting ideas at http://www.dostips.com/forum/viewtopic.php?t=1485 如果您真的想使用纯Windows批处理命令执行此操作,请参阅http://www.dostips.com/forum/viewtopic.php?t=1485上的一些有趣的想法

UPDATE : The latest version of scripts is here: https://sf.net/p/contools (scripts here: https://sf.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools/std/ ) 更新 :最新版本的脚本在这里: https//sf.net/p/contools (脚本在这里: https//sf.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools/std /

You can use some sequence to temporary replace special characters by placeholders like ?00, ?01, ?02 and ?03. 您可以使用某些序列来临时替换占位符,例如?00,?01,?02和?03。 I basically use these set of scripts: 我基本上使用这些脚本集:

replace_sys_chars.bat: replace_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: 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

Example: 例:

@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.---

test.txt: 的test.txt:

111/222
AAA=BBB
CCC=%DDD%
EEE=!FFF!
FFF=?00?01?02?03

Result: 结果:

"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"
---

Features : 特点

  • You can continue use standard batch variable arithmetic between conversions 您可以在转换之间继续使用标准批量变量算法
  • You can use character placeholders (?00, ?01, ?02, ?03) as plain variable values 您可以使用字符占位符(?00,?01,?02,?03)作为普通变量值

Why not use Edlin? 为什么不使用Edlin? I could not find a way to do this with one initial file and no errors from Edlin, but just ignore them with NUL:. 我找不到用一个初始文件做这个的方法而且Edlin没有错误,但是用NUL忽略它们: Strangly, the TYPE %0 includes the whole file even if there's an end of file character between the = and !, using TYPE on the batch file after it has run will not work the same way. 扼杀,即使在=和!之间存在文件结尾字符,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

My answer from another post, but it applies here, too: 我在另一篇文章中的回答,但也适用于此:

There is an alternative that is easier. 还有一种更容易的选择。 Instead of passing in a value that contains an equals sign, try something like a colon instead. 而不是传入包含等号的值,而是尝试使用冒号。 Then, through the ability to modify that value (the colon), you can convert it back into an equals. 然后,通过修改该值(冒号)的能力,您可以将其转换回等于。 Here is an example: 这是一个例子:

@echo off
set VALUE1=%1
set VALUE2=%VALUE1::==%
echo value1 = %VALUE1%
echo value2 = %VALUE2%

When you run the batch file, call it like this: 运行批处理文件时,请按以下方式调用它:

C:\>myBatch name:someValue

The output would be: 输出将是:

value1 = name:someValue
value2 = name=someValue

If the name or value contains a space, you will have other issues to address, though. 如果名称或值包含空格,则还需要解决其他问题。 You will need to wrap the entire string in double quotes. 您需要将整个字符串用双引号括起来。 But, then you have the issue of needing to get rid of them. 但是,那么你有需要摆脱它们的问题。 This can also be handled, like this: 这也可以处理,如下所示:

@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%

When running this batch file like this: 运行此批处理文件时,如下所示:

C:\>myBatch "some name:another value"

The output will be: 输出将是:

param = "some name:another value"
base  = some name:another value
pair  = some name=another value
name  = some name
value = another value

Hope that helps others in their quest to win the fight with batch files. 希望帮助其他人在他们的任务中赢得与批处理文件的斗争。

Mike V. 迈克五世

I was looking into this, because I needed to get rid of = in a string like "test=goingon" I found that calling a next batchfile with test=goingon as parameters, I have parameters 1, "test" and 2, "goingon", in that batchfile. 我正在研究这个问题,因为我需要在像“test = goingon”这样的字符串中删除=我发现调用下一个使用test = goon作为参数的批处理文件,我有参数1,“test”和2,“goon “,在该批处理文件中。

So: batchfile 1: 所以:batchfile 1:

@echo off
call test2.bat test=goingon

batchfile2: batchfile2:

echo arg1: %1
echo arg2: %2

result: 结果:

arg1: test
arg2: goingon

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM