Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to replace ! to %21 in batch elegantly?

i want to replace ! to %21(url encode) in batch,my code works,but not elegantly at all,any good ideal to finish the job in one line?

set pwd=!xxxxxxx
set pwd=%pwd:!=@21@%
setlocal enableDelayedExpansion
echo !pwd:@21@=%%21!
setlocal disabledelayedexpansion
like image 333
jils2013 Avatar asked Feb 08 '23 10:02

jils2013


1 Answers

Not only can I not simplify your code, I argue that your code is not complex enough.

Your code will fail if any of the following occur

  • The initial pwd value already contains @21@
  • The initial pwd value already contains %21. Presumably you would want to encode the % as %25
  • The initial value contains any poison character like &, |, <, >

Simply adding quotes cannot solve the poison character issue because presumably the value can also contain quotes. So a value like "this & that" & the other thing fails no matter how you quote it.

Here is robust code that can handle any set of characters except null, carriage return, and newline. I encode ! as %21, and % as %25. No other encoding is done.

@echo off
setlocal disableDelayedExpansion

:: Set and display the initial value
set pwd=;"This & that" ^& the other thing! %%25 %%21 @A @Q @P @E
echo Before encoding:
set pwd
echo(


:: Encoding begins here
  setlocal enableDelayedExpansion

  :: Protect @ as @A
  set "pwd=!pwd:@=@A!"

  :: Protect " as @Q
  set "pwd=!pwd:"=@Q!"

  :: Protect % as @P
  set "pwd=!pwd:%%=@P!"

  :: Encode ! as %21 in two steps
  set "pwd=%pwd:!=@E%"
  set "pwd=!pwd:@E=%%21!"

  :: Encode protected % as %25
  set "pwd=!pwd:@P=%%25!"

  :: Restore protected Q
  set "pwd=!pwd:@Q="!"

  :: Restore protected @
  set "pwd=!pwd:@A=@!"

  :: Display the result
  echo After encoding:
  echo !pwd!

endlocal

--OUTPUT--

Before encoding:
pwd=;"This & that" & the other thing! %25 %21 @A @Q @P @E

After encoding:
;"This & that" & the other thing%21 %2525 %2521 @A @Q @P @E

Sometimes you want to preserve the variable after the ENDLOCAL. This can easily be accomplished via FOR /F. Special syntax is required to disable both the EOL and DELIMS options.

I've removed all the comments to better show the amount of code required.

@echo off
setlocal disableDelayedExpansion

set pwd=;"This & that" ^& the other thing! %%25 %%21 @A @Q @P @E
echo Before encoding:
set pwd
echo(

setlocal enableDelayedExpansion
set "pwd=!pwd:@=@A!"
set "pwd=!pwd:"=@Q!"
set "pwd=!pwd:%%=@P!"
set "pwd=%pwd:!=@E%"
set "pwd=!pwd:@E=%%21!"
set "pwd=!pwd:@P=%%25!"
set "pwd=!pwd:@Q="!"
for /f delims^=^ eol^= %%A in ("!pwd:@A=@!") do (
  endlocal
  set "pwd=%%A"
)

echo After encoding:
set pwd

-- OUTPUT --

Before encoding:
pwd=;"This & that" & the other thing! %25 %21 @A @Q @P @E

After encoding:
pwd=;"This & that" & the other thing%21 %2525 %2521 @A @Q @P @E

Normally the simple FOR /F technique shown above only works when you start (and end) with delayed expansion disabled. Additional code would be needed to protect ! when %%A is expanded and delayed expansion is enabled. But since you have already encoded your ! as
%21, there is no problem if delayed expansion is enabled after ENDLOCAL.

like image 55
dbenham Avatar answered Feb 11 '23 23:02

dbenham