GetVar.bat and Eco.bat

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
carlsomo
Posts: 91
Joined: 02 Oct 2012 17:21

GetVar.bat and Eco.bat

#1 Post by carlsomo » 24 Jul 2013 21:57

I have 3 or 4 hairs left in my head after pulling them out in frustration as I tried to perfect these routines using batch only techniques to get these results.

GetVar.bat gets user input no matter how deviously poison characters are entwined and stores them in a variable name passed to the routine as arg1. Eco.bat spits it back out. Either bat file can be called from a delayed or not expansion environment - that was the hard part and thanks to the work by jeb, dbenham, aGerman and other notables who blazed the trail. Use Eco var and not Eco %var%.
So after all that....

Code: Select all

:GetVar.bat Var="Enter a variable string: " len /m
@echo off
if "%~1" equ "" goto :Help
if "%~1" equ "/?" goto :Help
SetLocal
set "NotDelayedFlag=!"
if Defined NotDelayedFlag EndLocal&goto :GetVar
EndLocal
:Called with Expansion Enabled
setlocal DisableDelayedExpansion
call :GetVar %*
set/a len=%errorlevel%
if /i %len% equ 0 EndLocal&set "%~1="&exit/b 0
SetLocal EnableDelayedExpansion
set "var=!%~1!"
set "Var=!Var:%%=%%~4!"
set "Var=!Var:"=%%~5!"
set "Var=!Var:^=^^^^!"
set "Var=%Var:!=^^^!%" !
set "replace=%% """ ."
for /F "tokens=1,2" %%4 in ("!replace!") do (
  EndLocal
  EndLocal
  set "%~1=%Var%" !
  @echo off
  exit/b %len%
)
goto :eof

:Help
echo(
echo(SYNTAX: GetVar.bat ^<EnVar^> [="User Prompt: "] [length] [/m]
echo(
echo(Assigns User input to the Environment variable passed as 1st argument
echo(Allows unbalance quotes and 'poison' characters mixed with quotes
echo(The only editing key available to the User is 'backspace'
echo(The user string entered is set in the Environment variable, 'Envar'
echo(If no arguments are passed or '/?' this help message is displayed
echo(The fisrt argument is mandatory, the rest are optional
echo(To display a variable with Poison chars and quotes use: Eco.bat
echo(To mask input with '*'s place /m at the very end of the argument list
echo(
echo(Example:
echo(
echo(GetVar.bat Pa$$word="Enter your 'Poison Password' string: " len /m
echo(Eco.bat "Your Poison Password is: '" Pa$$word "' with length: " len
exit/b 0

::**********************************::
::****||  SUBROUTINE VERSION  ||****::
::**********************************::

:GetVar
:: SYNTAX: GetVar ^<EnVar^> [="User Prompt: "] [length] [/m]
::
:: Assigns User input to the Environment variable passed as 1st argument
:: Allows unbalance quotes and 'poison' characters mixed with quotes
:: The only editing key available to the User is 'backspace'
:: The user string entered is set in the Environment variable, 'Envar'
:: If no arguments are passed the routine quits, stand alone version displays help
:: The fisrt argument is mandatory, the rest are optional
:: To display a variable with Poison chars and quotes use: Eco.bat
:: To mask input with '*'s place /m at the very end of the argument list
:: Must be called with delayed expansion disabled for '!', '^' and '&' in string
::
:: Example:
::
:: GetVar.bat Pa$$word="Enter your 'Poison Password' string: " len /m
:: Eco.bat "Your Poison Password is: '" Pa$$word "' with length: " len
:::
::: Dependencies - None           Author: Carl with ideas borrowed from Dostips.com
:::
  if "%~1"=="" goto :End_GetVar
  SetLocal DisableDelayedExpansion
  set "Masked="
  echo(%*|find /i " /m">nul
  if %errorlevel% equ 0 set "Masked=*"
  For /F %%# In ('"Prompt;$H&For %%# in (1) Do Rem"') Do Set "BS=%%#"
  Set "Line="
  if /i "%~2" neq "/m" <Nul set/p=".%BS% %BS%%~2"

:Char_Loop_
  Set "Key="
  For /F "delims=" %%# In (
     'Xcopy /L /W "%~f0" "%~f0" 2^>Nul'
  ) Do If Not Defined Key Set "Key=%%#"
  Set "Key=%Key:~-1%"
  SetLocal EnableDelayedExpansion
  If Not Defined Key ( Rem Enter pressed
     echo(
     If not Defined Line EndLocal&EndLocal&(
        If Defined %~1 Set "%~1="
        If Defined %~3 Set/a "%~3=0
     )&exit/b 0
     For /F delims^=^ eol^= %%# In ("!Line!") Do (
        EndLocal&EndLocal&(
           If not "%~3"=="" Set/a "%~3=%length%"
           If Not "%~1"=="" (Set "%~1=%%#")
           exit/b %length%
        )
     )
  )
  If %BS%==^%Key% (
     Set "Key="
     If Defined Line set/a length-=1& Set "Line=!Line:~0,-1!"& Set /P "=%BS% %BS%" <Nul
  ) Else (
     If defined Masked (Set "Display=*") Else (Set "Display=!Key:~-1!")
     set/a length+=1& Set /p=".%BS%!Display!" <Nul
  )
  If Not Defined Line (
     EndLocal& Set/a length=1& Set "Line=%Key%"
  ) Else For /F delims^=^ eol^= %%# In ("!Line!") Do (
     EndLocal& Set/a length=%length%& Set "Line=%%#%Key%"
  )
  Goto :Char_Loop_
:End_GetVar
EndLocal&exit/b 0


Code: Select all

@echo off&goto :Start_Eco
:Eco.bat "Display quoted strings mixed with " Variables " and more " Vars /n
echo(
echo(SYNTAX: Eco.bat "Envar variable is: '" Envar "'" /n "This is the next line"
echo(
echo(Environment variables may contain poison characters or quotes mixed in.
echo(Quoted strings wil be echo'd as is without the surrounding quotes.
echo('/n' will dsplay a line feed if it is not embedded in quotes.
echo(To assign a variable containing poison characters and quotes use: GetVar.bat
echo(&exit/b

:Start_Eco
if "%~1"=="" goto :Eco.bat
if "%~1"=="/?" goto :Eco.bat
::SetLocal DisableDelayedExpansion
For /F %%# In ('"Prompt;$H&For %%# in (1) Do Rem"') Do Set "BS=%%# %%#"
SetLocal EnableDelayedExpansion

:Start loop
if "%~1"=="" EndLocal&exit/b 0
if /i "/n" equ "%~1" (
  echo(
) else if not defined %1 (
  set "string=.%BS%%~1"
  for /f delims^=^ eol^= %%# in ("!string!") do EndLocal& set/p="%%#" <nul
  SetLocal EnableDelayedExpansion
) else ( <nul set/p=".%BS%!%~1!")
shift&goto :Start

:Without Delayed Expansion
for /f tokens^=^1^*^ delims^=^=^ eol^= %%a in ('set %~1') do set/p="%%b" <nul
:end
endlocal&exit/b 0

::**********************************::
::****||  SUBROUTINE VERSION  ||****::
::**********************************::

:Eco "Here is a char: " char " and a string: " EnvarString /n "This is line two."
::
:: Echo's strings mixed with environment variables with or without CR/LF or embed CR/LF inside
:: Environment variables must be passed by name (not reference) and may contain poison chars
:: Quoted strings are echo'd as is and may have leading or trailing spaces
:: To place a newline (CF/LF) use '/n' unquoted
:::
::: Dependencies - None
:::
  SetLocal DisableDelayedExpansion
  For /F %%# In ('"Prompt;$H&For %%# in (1) Do Rem"') Do Set "BS=%%# %%#"
  SetLocal EnableDelayedExpansion
  :Start_Eco
  if "%~1"=="" EndLocal&EndLocal&exit/b
  if /i "/n" equ "%~1" (
    echo(
  ) else if not defined %1 (
    set "string=.%BS%%~1"
    for /f delims^=^ eol^= %%# in ("!string!") do EndLocal& set/p="%%#" <nul
    SetLocal EnableDelayedExpansion
  ) else ( <nul set/p=".%BS%!%~1!")
  shift&goto :Start_Eco
:End_Eco

jeb
Expert
Posts: 1062
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: GetVar.bat and Eco.bat

#2 Post by jeb » 25 Jul 2013 02:33

Hi carlsomo,

nice work, but at some points it's overcomplicated.

As you only handle the case when the delayed expansion is enabled, and the inpuit can't contain CR nor LF,
this code should be enough.

Code: Select all

set "var=!var:^=^^^^!"
set "var=!var:"=""!"
set "var=%var:!=^^^!%" !
set "var=!var:""="!"
for /F "delims=" %%a in (""!var!"") do (
   endlocal
   set "%~1=%%~a" !
)


The "complex" version with the replace technic is only necessary when you use the line

Code: Select all

set "%~1=%var%" !

As there LF and CR would fail and percents can collide with for loop parameters.

jeb

carlsomo
Posts: 91
Joined: 02 Oct 2012 17:21

Re: GetVar.bat and Eco.bat

#3 Post by carlsomo » 25 Jul 2013 10:44

Thanks again, jeb

Post Reply