I am currently working on a batch file that is supposed to read a version number from another file.
Basically, I just need to extract the string from the other document and get the number from it (number changes over time).
set dir=..\folder1\file1.vcxproj
:: I want to get a string from %dir% with a specific beginning and then extract the version number from it
set string=... ("<PlatformToolset>*")
set vernum=... ("..>v142<..)
Thats what I want to achieve:
echo %string%
<PlatformToolset>v142</PlatformToolset>
echo %vernum%
142
I hope I could describe my problem. Unfortunately I have little experience with cmd and it is difficult for me to articulate myself in this respect.
I hope someone can still help :)
dir is a poor name for a variable for two reasons. First dir is a keyword in batch, and then it implies that it's a directory when it seems to be a file.
Use set "var1=value" for setting STRING values - this avoids problems caused by trailing spaces. Quotes are not needed for setting arithmetic values (set /a)
So presuming that what you're doing is to extract the 142 from the string <PlatformToolset>v142</PlatformToolset> found in the file dir (please change that name)
for /f "tokens=1,2delims=<> " %%b in ('type "%dir%"') do if "%%b"=="PlatformToolset" set "vernum=%%c"
set "vernum=%vernum:~1%"
note that the location and quote type (' or ") are critical.
The for reads each line of the file and analyses that line, assigning the first "token" (1) to %%b and the second (2) to %%c.
The line is regarded as being
<delimiter sequence><token1><delimiter sequence><token2><delimiter sequence><token3><delimiter sequence><token4>
A delimiter sequence is one or more of any of the characters specified in the delims= option; in this case, <, > and Space
So - where %%a (token 1) is PlatformToolset, we want to assign %%c (token 2) to vernum
so vernum will become v142 with a file containing the test line you've posted.
And the hieroglyphics behind the set command is explained by set /? from the prompt - it takes the value in vernum, starting at "character 1" (where the character numbering starts at 0) and assigns the result to the variable vernum
for more detail about for gymnastics, see for /? from the prompt.
Related
I've inherited a batch file which reads major, minor and build numbers from a text file as part of a long-established build process - the actual reading part code is a simple FOR /F:
FOR /F "tokens=1,2,3* delims=." %%A IN (C:\MyBuildArea\version.txt) DO (
SET Major=%%A
SET Minor=%%B
SET Build=%%C
)
However this is followed by the line:
SET Build=%Build: =%
I don't understand this last line - what it is doing. Guessing it might be trying to catch and remove a trailing space (?) from the original file read as the FOR /F was delimited on dot (".") not space.
Hoping someone can help me understand - is this line redundant or serving some purpose?
The command SET Build=%Build: =% will simply substitute all spaces with nothing, i.e. it will remove all spaces in the text stored in Build.
See set /? on command prompt for details.
I have a text file having the string:
pub:
04:d6:b6:f2:98:ff:94:d8:3c:36:ad:5f:86:40:aa:
d1:5a:e1:87:5d:55:9d:ad:8b:2b:fc:18:e7:bb:47:
7f:9f:9a:62:c6:19:3a:9e:65:62:4e:5e:98:6d:db:
0e:7d:f9:22:a3:ca:cb:12:b2:ed:eb:14:0c:b3:31:
59:02:17:6d:6a
I need to remove the 04 from the beginning of this and also remove the ':' from between the characters and print it like this, in a single line:
d6b6f298ff94d83c36ad5f8640aad15ae1875d559dad8b2bfc18e7bb477f9f9a62c6193a9e65624e5e986ddb0e7df922a3cacb12b2edeb140cb3315902176d6a
How can I do that using Windows commands?
quite straightforward:
#echo off
setlocal enabledelayedexpansion
set "first=true"
(for /f "eol=p delims=" %%a in (input.txt) do (
set "line=%%a"
if defined first (set "line=!line:~2!" & set "first=")
<nul set /p ".=!line::=!"
))>output.txt
Read the input file line by line.
Use a flag (first) to check for first line and remove the first two chars.
Remove the colons and
use <nul set /p to write without a line break.
Edit as it turned out in comments, your file has actually just one long line. This changes the way for processing to:
for /f %%a in (input.txt) do set "line=%%a"
set "line=%line:pub:04:=%"
set "line=%line::=%"
echo %line%
Note: variables can just hold a certain amount of data, so this apporach will fail, when the line exceeds this limit.
Your question is pretty confusing. You first say: "I have a text file having the string:", but the example data have six lines that could be taken as six strings, so at this point we have no idea of what the real data format is. Perhaps a single long line that you write here in six parts?
Next, you said "I need to remove the 04 from the beginning of this", but what happen if the data have not a 04 at the beginning? Perhaps you want to remove the first element even if it is not a 04?
In this way, we must assume several points in order to try to write a working solution.
The Batch file below read a file with several lines, remove the first line (even if it does not contain pub:), and remove the first colon-separated element (even if it is not 04):
#echo off
setlocal EnableDelayedExpansion
rem Read all lines, excepting the first one:
set "string="
for /F "skip=1" %%a in (input.txt) do set "string=!string!%%a"
rem Remove the first element:
set "string=%string:*:=%"
rem Show the rest, removing colons:
echo %string::=%
In this code there are other assumptions that are implicit in the way the commands work, like lines that does not contain spaces nor exclamation marks. Of course, if the real data file have a different format, this program will fail...
I have a source file that would look something like this:
Name SerialNumber
\\.\PHYSICALDRIVE1 000000002027612
\\.\PHYSICALDRIVE0 000000002027476
\\.\PHYSICALDRIVE2 00000000202746E
\\.\PHYSICALDRIVE3 00000000202760E
Using FOR loops in dos I need to be able to parse out just the number associated with each PHYSICALDRIVE entry to be used later in the bat file. eg: 1,0,2 and 3)
From what I gather the delims= only looks at one character at a time.
Since I can't say delims=PHYSICALDRIVE and have it treat that as a single delimiter.
Can anyone give an example on how to parse out only the numbers at the end of the string?
In case it matters Delayed expansion is being used.
Thanks.
I think any solution will require first parsing out the full column value, and then using SET search and replace or substring to parse out the number at the end.
I'm assuming the Name column value can never have a space within it. So the default FOR /F delimiters will parse out the 1st column easily enough.
If the drive number will always be less than 10 then
for /f %%A in (yourFileName.txt) do (
set "drive=%%A"
set "drive=!drive:~-1!"
echo !drive!
)
Else if it can be 10 or greater then
for /f %%A in (yourFileName.txt) do (
set "drive=%%~A"
set "drive=!drive:*physicaldrive=!"
echo !drive!
)
can anyone
tell me why in the example below the value of LIST is always blank
i would also like to only retrive the first 4 characters of %%i in variable LIST
cd E:\Department\Finance\edi\Japan_orders\
FOR /f %%i IN ('dir /b *.*') DO (
copy %%i E:\Department\Finance\Edi\commsfile.txt
set LIST=%%i
echo %LIST%
if %%i == FORD110509 CALL E:\Department\Finance\edi\EXTRACT.exe E:\Department\Finance\edi\COMMSFILE.TXT
)
pause
thanks in advance
You need delayed expansion. Add the following at the start of your program:
setlocal enabledelayedexpansion
and then use !LIST! instead of %LIST% inside of the loop.
For a thorough explanation please read help set.
Bracketed command blocks are parsed entirely, and it is done prior to their execution. Your %LIST% expression, therefore, is expanded at the beginning, while the LIST variable is still empty. When the time comes to execute echo %LIST%, there's not %LIST% any more there, only the empty string (read: 'nothing') instead. It's just how it works (don't ask me why).
In such cases the delayed expansion mechanism is used, and Joey has already told you that you need to use a special syntax of !LIST! instead of %LIST%, which must first be enabled (typically, by the command SETLOCAL EnableDelayedExpansion, which he has mentioned as well).
On your other point, you can extract a substring from a value, but the value must first be stored into a variable. Basically, the syntax for extracting substrings is one these:
%VARIABLE:~offset,charcount%
%VARIABLE:~offset%
That is, you are to specify the starting position (0-based) and, optionally, the number of characters to cut from the value. (If quantity is omitted then you are simply cutting the source string at the offset to the end.) You can read more about it by issuing HELP SET from the command line (wait, it's the same command that Joey has mentioned!).
One more thing: don't forget about the delayed expansion. You need to change the above % syntax to the ! one. In your case the correct expression for retrieving the first 4 characters would be:
!LIST:~0,4!
You can use it directly or you could first store it back to LIST and then use simply !LIST! wherever you need the substring.
Question about Batch/Windows/CMD:
I would like that my batch file can search for a line (which I already achieved, but what comes next not), it looks like this:
<name>MyName</name>
It needs to find the text in between <name> and </name>. After that it needs to set that as a variable (%name%).
Does anyone have any idea?
EDIT: if someone wants to give an answer, please list the code. Perl is OK, but this should be open-source and not everyone has Perl.
It can be done this way (assuming your input is in file "test1.html"):
findstr "<name>" test1.html > temp1.lis
FOR /F "tokens=2 delims=>" %%i in (temp1.lis) do #echo %%i > temp2.lis
FOR /F "tokens=1 delims=<" %%i in (temp2.lis) do #echo %%i > temp3.lis
The first line is a guard that only HTML/XML tag
"name" will match in the two FOR lines (you may
already have done this). The result is saved in a temporary
file, "temp1.lis".
The second line capture what is to the right of the first
">" - in effect what is after "<name>". At this stage
"MyName</name" is left in temporary file "temp2.lis" (as
the closing tag also contains ">"). Note the double "%"s
(%%i) as this is in a BAT file (if you want to test directly
from the command line then it should only be one "%").
The third line capture what is to the left of the first "<"
- this is the desired result: "MyName" (is left of "<" in
"MyName</name"). The result is in variable %%i and you
can call a function with %%i as a parameter and access the
result in that function (in the FOR line above the function
was the built-in "echo" and the result thus ended up in
temporary file "temp3.lis" by the redirection of standard
output)
Note that the above only works if
<name>MyName</name>
is the first HTML/XML tag in a line.
If that is not the case or you want a more robust solution
you can instead call a function in the first FOR line (that
receives %%i as the first parameter). That function can then
replace "<name>" with a single character that you are
sure is not in the input, e.g.:
set RLINE=%MYLINE:<name>=£%
Explanation: if the input line is in variable %MYLINE% then
"<name>" will be replaced with "£" and the result will be
assigned to variable %RLINE%.
The reason for the replace is that the delimiters for the
FOR loop are single character only.
You can then use "£" as a delimiter in the FOR loop (to extract what is
to the right of "<name>" - as before):
echo %RLINE%>temp5.lis
FOR /F "tokens=2 delims=£" %%i in (temp5.lis) do #echo %%i > temp6.lis
You have to repeat this technique for "</name>"
(but only if <name>MyName</name> is not
the first HTML/XML tag in a line).
So as you see it is possible, but is quite painful.
Learn Perl, it's made for exactly that kind of thing.