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

前端 未结 6 1799
孤独总比滥情好
孤独总比滥情好 2020-12-10 07:39

Besides SED, how can an equal sign be replaced? And how can I use a string variable in string replacement?

Consider this example:

For /F \"tokens=*\"         


        
相关标签:
6条回答
  • 2020-12-10 07:57

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

    @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
    
    0 讨论(0)
  • 2020-12-10 07:59

    Why not use 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:. 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.

    @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
    
    0 讨论(0)
  • 2020-12-10 08:01

    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.

    0 讨论(0)
  • 2020-12-10 08:03

    The setlocal enableDelayedExpansion should be moved after your old=%%B assignment in case %%B contains !.

    The "t" problem is easy to solve within a loop by using another FOR variable

    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.

    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

    0 讨论(0)
  • 2020-12-10 08:08

    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/)

    You can use some sequence to temporary replace special characters by placeholders like ?00, ?01, ?02 and ?03. I basically use these set of scripts:

    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:

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

    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
    0 讨论(0)
  • 2020-12-10 08:15

    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.

    So: batchfile 1:

    @echo off
    call test2.bat test=goingon
    

    batchfile2:

    echo arg1: %1
    echo arg2: %2
    

    result:

    arg1: test
    arg2: goingon
    
    0 讨论(0)
提交回复
热议问题