Interactive Command Prompt character escaping % - windows

I need to escape the % character in interactive Command Prompt (NOT in a batch file). How do I echo the text a %pathext% b; %pathext% expands to the environment variable; ^, %, \ and "quotes" all do not work. Please base the answer on: echo a %pathext% b.
Many thanks in advance.

There is one simple solution, but it's not 100% bullet proof
echo a %path^ext% b
The position of the caret can be moved to any position.
This works, because the variable expansion on the command line works different than in batch files.
If an undefined variable should be expanded, in a batch file it results in an empty text, but on the cli the percent expression will be used unchaged.
The caret will be removed in a later step of the parser.
But it can still fail when there exists a variable named path^ext
For a bullet proof solution, you need to create a percent sign and expand it.
for /F "delims==" %# in ("%=%=") do echo a %#pathext%# b

echo a %^pathext% b
Use a caret inside the variable (it can be anywhere inside the % signs) to prevent the parser from recognizing and substituting the variable.

Related

How to escape % inside double quotes in cmd?

In cmd I'm trying to do something like
program.exe -command "otherprogram.exe %thing% %path%"
The issue I'm having is that I can't figure out how to escape the % characters when they're inside double quotes, but I need the double quotes because of the spaces in this argument. Basically I don't want cmd to do variable expansion before passing the argument value to program.exe.
Just to be clear, this is directly in cmd, not in a batch script.
A simple semi solution is:
program.exe -command ^"otherprogram.exe %th^ing% %pa^t^h%^"
The positions of the carets inside the variable name are random.
This still could fail, but only for the rare case, if variables exists named thi^ng or pa^t^h
It seems strange, but don't escape the percent signs. Put a caret (the escape sign for every other special char) anywhere within the variable name: echo %^username% or `echo %use^rname%.
The first parsing removes the ^ (because there is (hopefully) no variable with that name). On command line (other than in a batch file), an empty variable doesn't show nothing, but the variable name including the surrounding %'s.
Any further level of parsing then receives the "normal" variable and expands it. Prove:
echo %usern^ame%
call echo %usern^ame%
Not your question, but for the sake of completeness: in a batch script, simply escape the % with another %:
echo %%username%%
call echo %%username%%

Windows bacth scripting: Problem exporting variable to txt

I have a variable with html code (having major, minor symbols)
and I need it to be exported and appended to a txt
set WORD1=^<p^>^<strong^>PROBLEM^</strong^> with something;n^</p^>
I can't echo the variable like this
echo %WORD1%
And I need to export it/append it to a file. I used:
echo %WORD1% >body.txt
But this generates an error as the variable has minor/Major symbol
If I double quote the variable, the exported text is exported with double quotes (and obviusly this is not what i need)
To define the variable, use:
set "WORD1=<p><strong>PROBLEM</strong> with something;n</p>"
To "export" the variable, use:
(
set /P "=%WORD1%"
echo/
) > body.txt < NUL
To define a variable in a safe way you need to enclose the whole assignment expression in quotation marks:
set "WORD1=<p><strong>PROBLEM</strong> with something;n</p>"
This avoids the need of escaping, unless the string itself contains quotation marks on its own.
Note that this syntax only works with command extensions enabled, but this is the default in Command Prompt anyway.
To return/expand an arbitrary string in a safe manner, even when it contains quotation marks on its own, is to use delayed variable expansion:
echo(!WORD1!
To safely write the output to a file, place the redirection expression at the front:
> "body.txt" echo(!WORD1!
You can also do this on one line:
set "WORD1=<p><strong>PROBLEM</strong> with something;n</p>"&&>body.txt cmd/v/cecho.!WORD1!
rem :: Or, without defining a previous variable, if it is not necessary:
>body.txt <nul set/P "=<p><strong>PROBLEM</strong> with something;n</p>"

How to assign a command line parameter which contains ! and & to a variable?

Please consider the following very simple batch script (the file is named test.cmd):
#echo off
set "var1=%~1"
echo %var1%
The script should be called with one command line parameter, should assign the string which is contained in that parameter to a variable, and should output the variable.
As expected, I get an error message when I call this script with a command line parameter which contains an ampersand (&):
C:\Batch>test "a&b"
a
'b' is not recognized as an internal or external command,
operable program or batch file.
The reason for this has been discussed in some other questions here and elsewhere, for example that one; the usual remedy is to use delayed expansion. So I changed the script accordingly:
#echo off
setLocal enableDelayedExpansion
set "var1=%~1"
echo !var1!
Now it works with the parameter from before:
C:\Batch>test "a&b"
a&b
But there is a new problem. When the command line parameter contains an exclamation mark (!), it will be dropped from the output:
C:\Batch>test a!b
ab
This behavior also has been discussed at several places, for example here; the crucial thing to note is that dropping the exclamation mark happens during the assignment, not during the echo.
Despite a lot of research, I did not find a question here which provided an elegant solution for both problems at once. That is, is there an elegant way to assign a command line parameter to a variable when that parameter contains an ampersand AND an exclamation mark?
It seems that I need the delayed expansion to treat the ampersand correctly, but this destroys the exclamation mark.
The only solution I currently see is to not use delayed expansion and to add code to explicitly quote all ampersands in the input string. This would be so ugly that I seriously think that I am missing something here.
As a side note, the reason for the problem actually seems to be that there (IMHO!) is no way to get the command line parameter in a delayed-expanded fashion. The syntax for the first parameter is %~1, there is no such thing as !~1.
Move the setLocal enableDelayedExpansion after the the set„ that's all.
#echo off
set "var1=%~1"
setLocal enableDelayedExpansion
echo !var1!

Batch script interpreting content inside comment?

When I run the following batch script:
#echo off
REM %~ will strip surrounding quotes if any
echo HERE
I get the following error:
C:\>test.cmd
The following usage of the path operator in batch-parameter
substitution is invalid: %~ will strip surrounding quotes if any
For valid formats type CALL /? or FOR /?
Same effect if REM is changed to ::.
Seems like the parser is ignoring the comment indicator and parsing the %~. If I put a space between the % and ~ then it works fine.
Windows 7 Enterprise (have not checked any other versions).
Seems like a bug to me, but am I missing something?
The %-expansion, hence expanding normal environment variables (like %VAR%) as well as command line arguments (like %0), is the very first step after having read a line, therefore it happens even before the rem command is recognised. Thus you need to avoid the %~ (by writing rem % + ~ ..., for instance).
Given that the command extensions are enabled, which is the default anyway, %~ is recognised as invalid argument syntax (the ~ is expected to be followed by a decimal digit denoting the argument position or by a valid modifier like f, d, p, n, x, etc.; see Command Line arguments (Parameters)) and results in a fatal error, meaning that an error message is thrown and batch file processing is aborted (the %ErrorLevel% is not set though).
The same effect comes up when you try to do sub-string substitution but specifying an empty search string (like %VAR:=replace% or %VAR:*=replace%, given that VAR is defined), also with command extensions enabled.
See also this thread: How does the Windows Command Interpreter (CMD.EXE) parse scripts?
I think it is clearly covered in quite a few docs that cmd will interpret the arguments before comments, see the example in #LotPings comment as well as #aschiphl's post. That being said, you can momentarily disableextensions and then turn it back on when needed. The below example shows how disabling it will allow you to use it in the REM comment and then enabled again after to show allow extensions:
#echo off
setlocal disableextensions
REM %~ will strip surrounding quotes if any"
endlocal
echo my batch file is %~0

Use an environment variable in a windows cmd file as substring length parameter

I need to output the first X characters of the content of OLD_ENTRY, say 33 chars. I grab the number of chars with another script. What is, in the following command in a Windows cmd script, the correct syntax to use a variable, say POS, instead of the hardcoded value 33?
echo %OLD_ENTRY:~0,33%
Thanks for any help,
Rip
Alright, I tend to call something like this as "nested variables". Anyway, to expand such nested variables, you need to establish a second parsing or expansion phase, and you need to ensure that the inner variable (POS) becomes expanded first, and the outer one (OLD_ENTRY) becomes expanded during the second phase. There are some options:
Using call:
This option avoids delayed variable expansion, which could be problematic with literal ! symbols, but it is quite slow, and it doubles quoted ^ characters:
In command prompt window:
call echo %^OLD_ENTRY:~0,%POS%%
This looks like "escaping" (^) the outer variable, but actually, this has got nothing to do with true escaping. In command prompt, an undefined variable does not become replaced by an empty string, it is just kept literally. So in the first pass, the undefined variable ^OLD_ENTRY is simply kept (you can verify that by defining such a variable by set "^OLD_ENTRY=something"), scanning for the closing % is skipped after the : for undefined variables strangely, the variable %POS% becomes expanded, and the last (orphaned) % is kept too; immediately after this phase, the escape sequence ^O is recognised, which results in a literal O; so we get echo %OLD_ENTRY:~0,33%, which becomes expanded in the second pass.
In a batch file:
call echo %%OLD_ENTRY:~0,%POS%%%
In the first pass, the first two consecutive percent symbols become replaced by one literal % sign, the variable %POS% becomes expanded, and the remaining two consecutive percent symbols become replaced by one literal % sign too, so we have echo %OLD_ENTRY:~0,33%, which becomes expanded in the second pass.
Using delayed variable expansion:
This is the better option, I think, because it is faster and does not mess around with ^:
echo !OLD_ENTRY:~0,%POS%!
This option works in both command prompt window and batch files. Here the first pass is the normal/immediate expanssion (%) which handles the %POS% variable, so the second pass the delayed expansion (!) receives echo !OLD_ENTRY:~0,33! to expand.
Refer also to this post: How does the Windows Command Interpreter (CMD.EXE) parse scripts?

Resources