I have a variable that I need to check if it contains spaces, and exit if it does.
I have this code:
if not [%VAR%]==[%VAR: =%] exit 1
.. but it does not work for spaces. I can use it for other characters though. For example looking for "/" works with same code:
if not [%VAR%]==[%VAR:/=%] exit 1
Is there a way to do it?
Thanks,
This should do as you need: double quotes are always the solution for spaces, and also with some other characters.
if not "%VAR%"=="%VAR: =%" exit 1
While the answer from foxidrive will handle the problem for simple cases and is the obvious answer (and yes, this is what i usually use), it will fail for values with a quote inside
"If needed" this should handle the marginal cases
for /f "tokens=2 delims= " %%a in (".%var:"=%.") do exit 1
The "trick" is to enclose the value with removed quotes and tokenize the string using for command. To avoid spaces at the start and end of the string from being removed a pair of aditional dots are included. If the string do not include a space, it will only have one token. But the for command is requesting the second token, so the code inside will not be executed for strings without a space in them.
Related
During the course of a batch file, a path like the following is stored in temp.txt:
c:\folder1\folder2\.
The period at the end is just because the path is generated from a for /r %%a in (.) statement. I try to get rid of this using the world famous jrepl.bat search and replace batch file, escaping the backslash with a double-backslash:
type temp.txt|jrepl "\\." "" >temp2.txt
Only problem is that this produces strange results because the search string is interpreted as a regular expression instead of a literal string. So then I tried this as instructed by the jrepl documentation:
type temp.txt|jrepl "\\." "" /l >temp2.txt
...but then for some reason nothing changes. The trailing \. at the end of the URL unfortunately remains intact. I have no idea what I'm doing wrong...
Just answered my own question. Once I added the /l option, I no longer needed to escape the backslash, so what works ends up being:
type temp.txt|jrepl "\." "" /l >temp2.txt
Almost deleted this whole question but figured maybe 2 more people might encounter this issue over the next 750 years, so what the heck.
I have a batch variable called version with this value "2930.2323 "
Now i want to remove the last character (or all spaces). I've tried both ways but the whitespace is not removed.
// MYVAR is set at the beginning of my batch file by another source code
SET "MYVAR=%MYVAR: =%"
Your code doesn't remove "Whitespaces", but SPACEs only (ie if it's a TAB it won't be removed unless you add another line to remove TABs too).
For your given string, I suggest another approach:
for %%a in (%myvar%) do set "myvar=%%a"
echo --%myvar%--
Note: that only works for whitespaces at the beginning or end of the string. A space in the middle of the string will split the string into two (or more). Also, some special characters will be problematic. But it will work with strings like your example ("Version numbers")
I am dealing with some code that was put together by someone who has long since left the company. It reads:
REM XX.XXX YYYYMMDD Author Description
REM version=4.3 &:20170418 comment comment comment
REM version=4.4 &:20170519 comment comment comment
SET version=4.5c &:20170604 comment comment comment
SET "version=%version: =%"
After puzzling through this, we finally figured out two things: one, that the & thing works to tell DOS that a new command is coming in the same line, and then the :date just gets thrown out because DOS doesn't know what to do with it.
But then we get to this SET "version=%version: =%" nonsense.
All I've been able to deduce from it so far is that it will remove spaces, so that if I did this instead:
SET version=4.5 c
SET "version=%version: =%"
ECHO %version%
I'll get "4.5c" echoed to the screen.
I can't find any information about this ": =%" business anywhere online. Is there a good reason to be doing this?
What Is Going On?:
This looks like Variable Edit/Replace or in other terms syntax-replacement. What this allows you to do is take a string, and replace characters or words from it and either replace the existing string or create a new modified one.
Taking example SET "version=%version: =%" This will be modifying the string version and removing all spaces from the string.
Positives To This Method:
Being that some strings or code need to be modified, you can very conveniently use a pure batch option to replace words in text files, remove words from string, add commas after words, and even remove the last x characters in a string.
syntax-replacement is commonly used for issues that that cannot be solved within a for loop or strings that need to be tweaked before being used, an example will be folder paths. In for loops, when processing strings containing \ and trying to use the delims=\, you sometimes need to change it to a less conflicting character as ; - SET "String=%String:\=;". The uses are endless.
Negatives To This Method:
This is a very easy way to edit strings but can come with a negative being that you cannot edit strings with special characters without first using an ^ to escape special characters in the base string. An Example of this will be the following:
SET "version=Hello & There" - This will break the syntax-replacement code as &
is calling a new command.
SET "version=Hello ^& There" - This is the proper way to "ignore" the & symbol
for processing.
Check out Set /? in a CMD window for more information.
The Problem
In a main batch file, values are pulled from a .txt file (and SET as values of variables within this batch file). These values may each contain % characters.
These are read from the .txt file with no issues. However, when a variable with a value containing a % character is passed to a second batch file, the second batch file interprets any % characters as a variable expansion. (Note: There is no control over the second batch file.)
Example
echo %PERCENTVARIABLE%
Output: I%LOVE%PERCENT%CHARACTERS%
When passed to a second file and then echo'ed, would (probably) become IPERCENT, as it interprets %LOVE% and %CHARACTERS% as unset variables.
Research
I found the syntax to find and replace elements within a string in a batch file, as I thought I could potentially replace a % character with %% in order to escape it. However I cannot get it to work.
The syntax is -
set string=This is my string to work with.
set string=%string:work=play%
echo %string%
Where the output would then be This is my string to play with..
Questions
Is it possible to escape % characters using the find and replace syntax
in a variable? (If not, is there another way?)
Is it advisable to do so? (Could using these escape characters cause any issue in the second batch file which (as mentioned above) we would have no control over?)
Is there another way to handle this issue, if the above is not possible?
There are no simple rules that can be applied in all situations.
There are a few issues that make working with string literals in parameters difficult:
Poison characters like &, |, etc. must be escaped or quoted. Escaping is difficult because it can be confusing as to how many times to escape. So the recommendation is to usually quote the string.
Token delimiters like <space>, <tab>, =, ; and , cannot be included in a parameter value unless it is quoted.
A CALL to a script will double any quoted % characters, and there is no way to prevent this. Executing a script without CALL will not double the % characters. But if a script calls another script and expects control to be returned, then CALL must be used.
So we have a catch-22: On the one hand, we want to quote parameters to protect against poison characters and spaces (token delimiters). But to protect percents we don't want to quote.
The only reliable method to reliably pass string literals without concern of value corruption is to pass them by reference via environment variables.
The value to be passed should be stored in an environment value. Quotes and/or escapes and/or percent doubling is used to get the necessary characters in the value, but it is very manageable.
The name of the variable is passed in as a parameter.
The script accesses the value via delayed expansion. For example, if the first parameter is the name of a variable containing the value, then it is accessed as !%1!. Delayed expansion must be enabled before that syntax can be used - simply issue setlocal enableDelayedExpansion.
The beauty of delayed expansion is you never have to worry about corruption of poison characters, spaces, or percents when the variable is expanded.
Here is an example that shows how the following string literal can be passed to a subroutine
"<%|,;^> This & that!" & the other thing! <%|,;^>
#echo off
setlocal enableDelayedExpansion
set "parm1="^<%%^|,;^^^^^> This ^& that^^!" & the other thing^! <%%|,;^^^>"
echo The value before CALL is !parm1!
call :test parm1
exit /b
:test
echo The value after CALL is !%1!
-- OUTPUT --
The value before CALL is "<%|,;^> This & that!" & the other thing! <%|,;^>
The value after CALL is "<%|,;^> This & that!" & the other thing! <%|,;^>
But you state that you have no control over the 2nd called script. So the above elegant solution won't work for you.
If you were to show the code of the 2nd script, and show exactly what value you were trying to pass, then I might be able to give a solution that would work in that isolated situation. But there are some values that simply cannot be passed unless delayed expansion is used with variable names. (Actually, another option is to put the value in a file and read the value from the file, but that also requires change to your 2nd script)
may be...?
input.txt
I%LOVE%PERCENT%CHARACTERS%
batch1.bat
#echo off
setlocal enableDelayedExpansion
set/P var=<input.txt
echo(In batch 1 var content: %var%
set "var=!var:%%=%%%%!"
call batch2.bat "%var%"
endlocal
exit/B
batch2.bat
#echo off
set "var=%~1"
echo(In batch 2 var content: %var%
exit/B
Sample batch execution:
test.bat /s v1.1 1,3,4,5
I want to split the parameter into three tokens using space as a delimiter. The result should be:
1st token = /s
2nd token = /v1.1
3rd token = 1,3,4,5
Then the 3rd token will be split again using comma as a delimiter
The code below splits the arguments using common delimiters such as space, comma, etc.
#ECHO OFF
SET PARAMS=
:_PARAMS_LOOP
SET PARAMS=%PARAMS%%1
ECHO %1
SHIFT
IF NOT "%1"=="" GOTO _PARAMS_LOOP
Execution:
test.bat /s v4.1 1,2,3,4
Result:
/s
v4.1
1
3
4
5
I just want to use space as a delimiter, then in the 3rd token(1,3,4,5) I will split it again using comma as a delimiter and echo each of it.
The issue is that cmd recognizes a space, tab, comma, semicolon, or equals sign as command line delimiters unless they are wrapped in doublequotes.
Delimiters
Some characters in the command line are ignored by batch files,
depending on the DOS version, wether they are "escaped" or not, and
often depending on their location in the command line:
commas (",") are replaced by spaces, unless they are part of a string
in doublequotes
semicolons (";") are replaced by spaces, unless they
are part of a string in doublequotes
"=" characters are sometimes
replaced by spaces, not if they are part of a string in doublequotes
the first forward slash ("/") is replaced by a space only if it
immediately follows the command, without a leading space
multiple spaces are replaced by a single space, unless they are part of a
string in doublequotes
tabs are replaced by a single space
leading spaces before the first command line argument are ignored
I know of several occasions where these seemingly useless "features" proved very
handy. Keep in mind, though, that these "features" may vary with the
operating systems used.
More on command line parsing can be found on the PATH and FOR
(especially FOR's interactive examples) pages.
http://www.robvanderwoude.com/parameters.php