2016-02-06 2 views
6

Я пытаюсь заменить все экземпляры ~{~} в пакетном скрипте, чтобы VBScript не предполагал, что я хочу нажать Enter, когда я передаю его sendKeys, однако переменная продолжает заменяться литеральной строкой, предназначенной для замени это.Как избежать «~» в команде set/replace?

Например,

rem Intended function; 
rem input = Hello~world. 
rem output = Hello{~}world. 

Однако каждый раз, когда он либо ничего не делает, или устанавливает refVar до символьной строки refVar:~={~}.

Вот что я пробовал;

set refVar=!refVar:~={~}! 

rem Also 
set refVar=%refVar:~={~}% 

rem and... 
set refVar=%refVar:^~=^{^~^}% 

rem and of course; 
set refVar=!refVar:^~=^{^~^}! 

rem and even: 

set "pre=~" 
set "post={~}" 
set refVar=%refVar:!pre!=!post!% 

rem and the same set commands with; 
set refVar=!refVar:%pre%=%post%! 

Я пропустил способ избежать этого? Я почти уверен, что это связано с ~, являющимся позиционным символом в подобной команде.

Я понимаю, что есть способ исправить это в VBScript, но это мешает мне иметь ограничение без видимых обходных решений.

ответ

2

I предлагают, возможно, более простое решение для замены каждого символа тильды в строке значений переменной окружения тильдой в фигурных скобках, чем Dennis van Gils, которая также отлично подходит для этой задачи.

@echo off 
set "TestVar=hello~world." 
echo TestVar has value: %TestVar% 
call :SpecialReplace "TestVar" 
echo TestVar has value: %TestVar% 
goto :EOF 


rem The subroutine below expects the name of an environment variable as 
rem parameter. The subroutine does nothing if called without parameter. 
rem Also nothing is done if specified environment variable is not defined. 

rem Each tilde character in value of this environment variable is replaced 
rem by {~} by this subroutine. 

rem Note: This subroutine can be also easily modified to replace other 
rem special characters like the equal sign by a different string which 
rem can be also no string in case of special character should be removed. 
rem Just modify Search and Replace variables for a different replace. But 
rem be aware of more code must be changed if search string is longer than 
rem one character. Length of replace string does not matter on code below. 

:SpecialReplace 
if "%~1" == "" exit /B 
setlocal EnableDelayedExpansion 
set "VarName=%~1" 
set "VarValue=!%VarName%!" 
if "!VarValue!" == "" endlocal & exit /B 
set "NewValue=" 
set "Search=~" 
set "Replace={~}" 

:ReplaceLoop 
if "!VarValue:~0,1!" == "!Search!" (
    set "NewValue=!NewValue!!Replace!" 
) else (
    set "NewValue=!NewValue!!VarValue:~0,1!" 
) 
set "VarValue=!VarValue:~1!" 
if not "!VarValue!" == "" goto ReplaceLoop 
endlocal & set "%VarName%=%NewValue%" & exit /B 

Для понимания используемых команд и как они работают, откройте окно командной строки, выполните там следующие команды, и читать полностью все справочные страницы отображаются для каждой команды очень тщательно.

  • call /?
  • echo /?
  • endlocal /?
  • exit /?
  • goto /?
  • if /?
  • rem /?
  • set /?
  • setlocal /?

И смотри также ответить на Single line with multiple commands using Windows batch file, чтобы понять, как эти две строки с несколькими командами с одной амперсанд между командами работы.


Вариант выше с расширенной поддержкой подпрограммы SpecialReplace Теперь переменную строки поиска и замены, указанные в качестве второй и третий параметр, как предложено Dennis van Gils.

@echo off 
set "TestVar=hello~world." 
echo TestVar has value: %TestVar% 
call :SpecialReplace "TestVar" "~" "{~}" 
echo TestVar has value: %TestVar% 
goto :EOF 


rem The subroutine below expects the name of an environment variable as 
rem first parameter. The subroutine does nothing if called without parameter. 
rem Also nothing is done if specified environment variable is not defined. 

rem The second parameter must be the search string. The subroutine does 
rem nothing if there is no second parameter which can be also just one 
rem or two double quotes enclosed in double quotes. 

rem The third parameter is an optional replace string. Without a third 
rem parameter all occurrences of search string are removed from value 
rem of the specified environment variable. 

rem With just one or two double quotes in double quotes as search string 
rem no replace string can be defined because command processor does not 
rem parse the quote strings as most would expect it. But """ or """" as 
rem search string with no replace string works and results in removing 
rem all double quotes or all occurrences of two double quotes. 

:SpecialReplace 
if "%~1" == "" exit /B 
setlocal EnableDelayedExpansion 
set "VarName=%~1" 
set "VarValue=!%VarName%!" 
if "!VarValue!" == "" endlocal & exit /B 
set "NewValue=" 
set "Search=%~2" 
if "!Search!" == "" endlocal & exit /B 
set "Replace=%~3" 
set "Length=0" 

:GetLength 
if "!Search:~%Length%,1!" == "" goto ReplaceLoop 
set /A Length+=1 
goto GetLength 

:ReplaceLoop 
if "!VarValue:~0,%Length%!" == "!Search!" (
    set "NewValue=!NewValue!!Replace!" 
    set "VarValue=!VarValue:~%Length%!" 
) else (
    set "NewValue=!NewValue!!VarValue:~0,1!" 
    set "VarValue=!VarValue:~1!" 
) 
if not "!VarValue!" == "" goto ReplaceLoop 
endlocal & set "%VarName%=%NewValue%" & exit /B 
+0

Это действительно аккуратный ответ. Лучше использовать аргументы для строки поиска и замены, чтобы упростить ее использование. –

+0

Ха-ха, я знаю команды командного сценария по большей части, но я предполагаю, что команды справки для других ищут тот же ответ. В любом случае, спасибо, рад узнать, что решение - это не просто определенный порядок разделителей, которые я не смог попробовать. – Bloodied

+0

@Arescet Да, я добавил список используемых команд и как получить помощь по ним для всех, кто читает этот ответ, поскольку я почти всегда делаю ответы на свои ответы в пакете. Для меня было очевидно, что вы хорошо знаете все эти команды. – Mofi

4

Так что я сделал некоторые копания, и кажется, это действительно, очень сложно. Тем не менее, я нашел this, который решает эту проблему, давая нам это как код:

@echo off 

set "input=Hello~world." 
echo input: %input% 

call :wavereplacer "%input%" {tilde} output 
set output=%output:{tilde}={~}% 
echo output: %output% 
pause 

::your own code should be above this. 
goto :eof 

:wavereplacer String Replacer [RtnVar] 
setlocal 
rem the result of the operation will be stored here 
set "result=#%~1#" 
set "replacer=%~2" 
call :strlen0.3 result wl 
call :strlen0.3 replacer rl 

:start 

    set "part1=" 
    set "part2=" 

    rem splitting the string on two parts 
    for /f "tokens=1* delims=~" %%w in ("%result%") do (
    set "part1=%%w" 
    set "part2=%%x" 
) 

    rem calculating the count replace strings we should use 
    call :strlen0.3 part1 p1l 
    call :strlen0.3 part2 p2l 
    set /a iteration_end=wl-p1l-p2l 

    rem creating a sequence with replaced strings 
    setlocal enableDelayedExpansion 
    set "sequence=" 
    for /l %%i in (1,1,%iteration_end%) do (
    set sequence=!sequence!%replacer% 
) 
    endlocal & set "sequence=%sequence%" 

    rem adjust the string length 
    set /a wl=wl+iteration_end*(rl-1) 

    rem replacing for the current iteration 
    set result=%part1%%sequence%%part2% 
    rem if the second part is empty the task is over 
    if "%part2%" equ "" (
    set result=%result:~1,-1% 
    goto :endloop 
) 


    goto :start 

:endloop 
endlocal & if "%~3" neq "" (set %~3=%result%) else echo %result% 
exit /b 

:strlen0.3 StrVar [RtnVar] 
    setlocal EnableDelayedExpansion 
    set "s=#!%~1!" 
    set "len=0" 
    for %%A in (2187 729 243 81 27 9 3 1) do (
    set /A mod=2*%%A 
    for %%Z in (!mod!) do (
     if "!s:~%%Z,1!" neq "" (
     set /a "len+=%%Z" 
     set "s=!s:~%%Z!" 

    ) else (
     if "!s:~%%A,1!" neq "" (
      set /a "len+=%%A" 
      set "s=!s:~%%A!" 
     ) 
    ) 
    ) 
) 
    endlocal & if "%~2" neq "" (set %~2=%len%) else echo %len% 
exit /b 

Это не может заменить ~ на {~} сразу, вам нужно использовать временную замену, в этом случае {tilde}

1
@ECHO Off 
SETLOCAL ENABLEDELAYEDEXPANSION 
SET "input=hello~world" 

SET "xhead=!input:%input:*~=%=!" 
SET "output=!input:%xhead%=%xhead:~0,-1%{~}!" 

ECHO %input% --^> %output% 

GOTO :EOF 

Это, как представляется, работать при условии, есть ровно один ~ и что это не начальный или конечный символ.

Смежные вопросы