I am working on a batch file that get's data as a variable, and in that variable it has an exclamation mark.
What i am trying to do is add the necessary escape characters to the variable.
"Title":"Turk 182!"
Above is an example of the data I am working with.
setlocal EnableDelayedExpansion
rem replace ! with ^^!
set var=%var:!=^^!!%
But I am not sure that is the correct syntax, since how can i escape an esclamation mark if it's also used as part of the search and replace?
I am trying to replace all esclamation mark with an escaped version so it can be displayed and worked with.
Btw, is there any existing functions in batch that will remove and allow escaping of all special characters?
Here is more code that may help explain what I am doing.
{"Title":"Turk 182!","Year":"1985","Rated":"PG-13","Released":"15 Feb 1985","Runtime":"1 h 42 min","Genre":"Action, Comedy, Drama","Director":"Bob Clark","Writer":"Denis Hamill, James Gregory Kingston","Actors":"Timothy Hutton, Robert Urich, Kim Cattrall, Robert Culp","Plot":"Jimmy Lynch is angry because his older brother, who was injured as a result of an off duty fire rescue...","Poster":"http://ia.media-imdb.com/images/M/MV5BMTQ2OTk1ODA1MV5BMl5BanBnXkFtZTcwNjYwNjgyMQ@@._V1_SX300.jpg","imdbRating":"5.7","imdbVotes":"2,360","imdbID":"tt0090217","Response":"True"}
rem removes starting and ending brackets
set json=%json:~1,-1%
setlocal EnableDelayedExpansion
rem replace "," with linebreak
set json=!json:","="#"!
setlocal EnableDelayedExpansion
rem replace ! with ^^!
set json=%json:!=^^!!%
setlocal DisableDelayedExpansion
echo %json%
echo.
exit /b
Then i place the json variable in the loop and it error's out instead of the true value I just see the actual replace command i used above.
Jaime Ramos sent me this link where the solution can be found: use ^^! . The trick is that a single caret will be used to escape the exclamation mark in the first "pass" of command line interpretation, but delayed variable expansion adds a second "pass" where the exclamation mark will be interpreted.
Represents a replaceable parameter. Use a single percent sign ( % ) to carry out the for command at the command prompt. Use double percent signs ( %% ) to carry out the for command within a batch file. Variables are case sensitive, and they must be represented with an alphabetical value such as %a, %b, or %c. ( <set> )
%0 is the name of the batch file. %~n0 Expands %0 to a file Name without file extension.
I'm not convinced you really need to escape !
. It is possible to do, but as jeb tried to explain, it can get complicated.
Based on the code you provided, it looks to me like you do not understand what delayed expansion does. I suggest you type HELP SET
from a command prompt and read the documentation. The description of delayed expansion begins about half way down with the line that reads "Finally, support for delayed environment variable expansion..."
There are other major benefits to delayed expansion. One of the biggest advantages is you never have to worry about escaping any special characters when you use delayed expansion. Escaping characters while using normal expansion is a pain, and can be extremely confusing until you gain experience. (It really is logical and predictable, but until you understand it, it looks like gibberish)
The biggest problem with delayed expansion is it does not play nice with FOR loops when the data contains !
. That is because the delayed expansion occurs after the FOR variable is expanded, so values containing !
will be corrupted. In my json parser below, I toggle the delayed expansion off within the loop to avoid that problem.
I don't know much about json, so my solution below may be naive (incomplete). But here is a simple json parser that works with the data you provided. I put your json string in a file named "test.txt"
@echo off
setlocal disableDelayedExpansion
setlocal enableDelayedExpansion
::Read the json string from a file
<test.txt set /p "json="
::Define LF variable to contain a linefeed
set LF=^
::The above 2 blank lines are critical - DO NOT REMOVE
::Strip the enclosing braces
set "json=!json:~1,-1!"
::Substitute a linefeed for ","
for %%A in ("!LF!") do set "json=!json:","=%%~A!"
::Substitute = for ":"
set "json=!json:":"==!"
::Remove remaining "
set "json=!json:"=!"
::Loop through the data, creating variables of the form var_name=value
for /f "delims=" %%A in ("!json!") do (
REM If delayed expansion is enabled then endlocal to get back to disabled state
if "!!" equ "" endlocal
REM Create the variable
set "var_%%A"
)
::Display the results - list all variables that begin with var_
set var_
Here is the output
var_Actors=Timothy Hutton, Robert Urich, Kim Cattrall, Robert Culp
var_Director=Bob Clark
var_Genre=Action, Comedy, Drama
var_imdbID=tt0090217
var_imdbRating=5.7
var_imdbVotes=2,360
var_Plot=Jimmy Lynch is angry because his older brother, who was injured as a result of an off duty fire rescue...
var_Poster=http://ia.media-imdb.com/images/M/MV5BMTQ2OTk1ODA1MV5BMl5BanBnXkFtZTcwNjYwNjgyMQ@@._V1_SX300.jpg
var_Rated=PG-13
var_Released=15 Feb 1985
var_Response=True
var_Runtime=1 h 42 min
var_Title=Turk 182!
var_Writer=Denis Hamill, James Gregory Kingston
var_Year=1985
If you are enable delayed expansion, you shouldn't use percent expansion with special characters.
If you are using delayed expansion instead you don't get problems with exclamation marks or other characters.
set myTitle="Turk 182!"
setlocal EnableDelayedExpansion
echo Title=!myTitle!
You could replace the exclamation marks, but you need mutliple carets and the count depends on many things.
As small sample why percent expansion isn't the best choice
@echo off
set test1=An exclamation mark^^^^!
setlocal EnableDelayedExpansion
set test2=An exclamation mark^^^^^^^^^^!
set "test3=An exclamation mark^^^^^!"
set test4a=An exclamation mark^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
set test4b=%test4a%!
echo %test1%
echo %test2%
echo %test3%
echo %test4b%
If you want to read text from a file in a secure way, you can use the delayed toggling technic.
setlocal DisableDelayedExpansion
for /F "delims=" %%a in (myFile.txt) DO (
set "line=%%a"
setlocal EnableDelayedExpansion
echo !line!
endlocal
)
you can use PowerShell:
$json=@"
{"Title":"Turk 182!","Year":"1985","Rated":"PG-13","Released":"15 Feb 1985","Runtime":"1 h 42 min","Genre":"Action, Comedy, Drama","Director":"Bob Clark","Writer":"Denis Hamill, James Gregory Kingston","Actors":"Timothy Hutton, Robert Urich, Kim Cattrall, Robert Culp","Plot":"Jimmy Lynch is angry because his older brother, who was injured as a result of an off duty fire rescue...","Poster":"http://ia.media-imdb.com/images/M/MV5BMTQ2OTk1ODA1MV5BMl5BanBnXkFtZTcwNjYwNjgyMQ@@._V1_SX300.jpg","imdbRating":"5.7","imdbVotes":"2,360","imdbID":"tt0090217","Response":"True"}
"@
add-type -assembly system.web.extensions
$jserial = new-Object Web.Script.Serialization.JavaScriptSerializer
$jserial.DeserializeObject($json)
Key Value
--- -----
Title Turk 182!
Year 1985
Rated PG-13
Released 15 Feb 1985
Runtime 1 h 42 min
Genre Action, Comedy, Drama
Director Bob Clark
Writer Denis Hamill, James Gregory Kingston
Actors Timothy Hutton, Robert Urich, Kim Cattrall, Robert Culp
Plot Jimmy Lynch is angry because his older brother, who was ..
Poster http://ia.media-imdb.com/images/M/MV5BMTQ2OTk1ODA1MV5BMl..
imdbRating 5.7
imdbVotes 2,360
imdbID tt0090217
Response True
or with PowerShell v3:
PS III> $json | ConvertFrom-JSON
Key Value
--- -----
Title Turk 182!
Year 1985
Rated PG-13
Released 15 Feb 1985
Runtime 1 h 42 min
Genre Action, Comedy, Drama
Director Bob Clark
Writer Denis Hamill, James Gregory Kingston
Actors Timothy Hutton, Robert Urich, Kim Cattrall, Robert Culp
Plot Jimmy Lynch is angry because his older brother, who was ..
Poster http://ia.media-imdb.com/images/M/MV5BMTQ2OTk1ODA1MV5BMl..
imdbRating 5.7
imdbVotes 2,360
imdbID tt0090217
Response
jeb and dbenham fully answered the question already, so this is somewhat off topic...
I used a small trick to avoid the hassle of remember how many carets I must insert in order to use an exclamation mark in diverse situations. I define a variable with Delayed Expansion disabled and assign to it an exclamation mark (I called it bang). Then I Enable Delayed Expansion and use it as !bang!. This way, this value will always appear as an exclamation mark and it is very easy to write...
@echo off
setlocal DisableDelayedExpansion
set bang=!
setlocal EnableDelayedExpansion
echo Yes, it works!bang!
Antonio
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With