Have done quite a bit of searching for a guide (of any substance) for the above to no avail. Can anyone refer me to one?
In the present tense however, I am trying to understand the below code example, which returns a two digit representation of the month, that corresponds to the 3 character month name set in v:
SET v=May
SET map=Jan-01;Feb-02;Mar-03;Apr-04;May-05;Jun-06;Jul-07;Aug-08;Sep-09;Oct-10;Nov-11;Dec-12
CALL SET v=%%map:*%v%-=%%
SET v=%v:;=&rem.%
ECHO.%v%
SET v=May Set the variable
SET map=Jan-01;Feb-02;Mar-03;Apr-04;May-05;Jun-06;Jul-07;Aug-08;Sep-09;Oct-10;Nov-11;Dec-12 Set the substitution string
CALL SET v=%%map:*%v%-=%% - Set %v to the map, but replace everything up to %v%- with nothing
(: replace * everything up to and including May- with nothing (no substitution code after =) - v is now 05;Jun-06;Jul-07;Aug-08;Sep-09;Oct-10;Nov-11;Dec-12
SET v=%v:;=&rem.% replace ; with &rem sets up a line that sets v to 05 and the & rem comments out all the other parts of the command. The command executed is SET v=05 & rem.Jun-06 & rem.Jul-07 & rem.Aug-08 & rem.Sep-09 & rem.Oct-10 & rem.Nov-11 & rem.Dec-12
ECHO.%v% gives the answer
This site gives a lot of info, but running the batch file, and putting echo %v% will also help
Excuse me. I don't like this type of code. In my personal opinion, it is much clear to manage these values as an array this way:
rem Prepare the array of two-digits values for each 3-letters month names:
for %%a in ("Jan=01" "Feb=02" "Mar=03" "Apr=04" "May=05" "Jun=06" "Jul=07" "Aug=08" "Sep=09" "Oct=10" "Nov=11" "Dec=12") do (
set month%%~a
)
rem Previous code is equivalent to these 12 lines:
rem set monthJan=01
rem set monthFeb=02
. . . .
rem set monthDec=12
rem This way, the result is immediately accessible:
SET v=May
CALL SET v=%%month%v%%%
rem Or in the clearer way using Delayed Expansion:
SET v=!month%v%!
monthXXX is an array of values for 12 different 3-letters month names.
SET v=May set the value of the index to an element array.
SET v=!month%v%! is first expanded to SET v=!monthMay! (normal expansion), and then to SET v=05 (Delayed Expansion).
I had explained the reasons I have to prefer this notation with every detail in these posts:
Arrays, linked lists and other data structures in cmd.exe (batch) script
DIR output into BAT array?
I apologize if someone thinks this answer is off-topic...
Antonio
For those who wants the other way around, and wanted an error if the entered month number is wrong, put this in a file named script.cmd:
#echo off
set mNum=%1
set mMap=01-Jan;02-Feb;03-Mar;04-Apr;05-May;06-Jun;07-Jul;08-Aug;09-Sep;10-Oct;11-Nov;12-Dec
call set mName=%%mMap:*%mNum%-=%%
set mName=%mName:;=&rem.%
if "%mName%" == "01-Jan" (
echo Wrong month number "%mNum%"!
goto :EOF
)
echo Month %mNum% is "%mName%".
And start the script with a parameter:
> script 02
Month 02 is "Feb".
> script 13
Wrong month number "13"!
> script foo
Wrong month number "foo"!
However, it does not cover an empty value:
> script
Month is "Jan".
Related
I have tried multiple things with a code like this.
#echo off
set %1%=A
set %2%=B
set %3%=C
set %4%=D
set %5%=E
set %6%=F
set %7%=G
set %8%=H
echo %1%%2%%3%%4%%5%%6%%7%%8%%9%
But kinda nothing worked, the output was this:
1%2%3%4%5%6%7%8
How do I get it to output ABCDEFGH?
Try with
#echo off
set _1=A
set _2=B
set _3=C
set _4=D
set _5=E
set _6=F
set _7=G
set _8=H
echo %_1%%_2%%_3%%_4%%_5%%_6%%_7%%_8%
Starting from the concept, your problem is that %n with n in the range 0..9 is handled by the batch parser as an command line argument to the batch file, not a variable expansion operation.
You can use number prefixed variable names, but then you will require to enable delayed expansion and change the variable expansion syntax from %varName% in to !varName! to be able to retrieve the value. It is easier not use number prefixed variables names.
The second problem is that the syntax %varName% is only used where the variable value needs to be retrieved. When you set the value, the syntax is set varName=varValue, or still better you can quote the operation as set "varName=varValue" to avoid problems with special characters and inclusion of unneeded ending spaces.
Your question is not clear. The code below do exactly what you requested:
#echo off
set A=A
set B=B
set C=C
set D=D
set E=E
set F=F
set G=G
set H=H
echo %A%%B%%C%%D%%E%%F%%G%%H%
However, is likely that this obvious solution is not what you are looking for...
If you want to know if is there a way to "automatically" define a series of variables and process they all, then the solution is to use an array. You may read the description of the array concept in this Wikipedia article and a detailed explanation of array management in Batch files at this answer. For example:
#echo off
setlocal EnableDelayedExpansion
rem Create "a" array with all elements given:
set n=0
for %%a in (A B C D E F G H) do (
set /A n=n+1
set a[!n!]=%%a
)
rem Show the 8 elements of "a" array
echo %a[1]%%a[2]%%a[3]%%a[4]%%a[5]%%a[6]%%a[7]%%a[8]%
rem Join *all* the elements of "a" array in a single variable
set "all="
for /L %%i in (1,1,%n%) do set "all=!all!!a[%%i]!"
echo %all%
Note that the last example works correctly no matters how many elements have been defined in "a" array.
Although you may also write the array elements in a shorter way, ommiting the braquets: set "a1=A" & set "a2=B", etc, and then use echo %a1%%a2%..., you should remember that the use of braquets is a standard notation used in many other programming languages, so it is convenient to keep it.
As you can see in my script bellow, the %pin%count%% (maybe obviously for some of you) won't return the wanted value but the string value of the wanted variable, as %pin5% for instance.
I've created a script where the number of variables will depend on how many colors the user chose for his pins. The troubling part of the script is:
Echo - Please type the colors of the pins allowed in the purchase,
or type dot (.) to finish this part of the script.
set count=0
:Pin
set /a count=%count%+1
set /p pin%count%=
if not %pin%count%%=="." goto Pin
I cannot use the IF statement because %pin%count%% returns %pin1% or %pin2% but not the value itself, how to solve this?
It seems like a simple enough syntax problem, but i'm trying everything and haven't managed to solve it yet and asking may be the fastest solution.
to evaluate a composite variable name, you have to use setlocal enabledelayedexpansion so you can specify ! as an extra delimiter,
The other problem you had is that you compared the variable with ".". Batch does not remove quotes like bash does. Don't put the quotes, or put some quotes on the left end too.
Fixed code:
#echo off
Echo - Please type the colors of the pins allowed in the purchase,
echo or type dot (.) to finish this part of the script.
setlocal enabledelayedexpansion
set count=0
:Pin
set /a count+=1
set /p pin%count%=
rem echo the variable for debug purposes
echo pin%count% = !pin%count%!
rem here's the tricky line
if not !pin%count%!==. goto Pin
How would I capture the time down the second into a variable using a batch file. My script right now looks like this.
CLS
#ECHO OFF
set yy=%date:~-4%
set mm=%date:~-7,2%
set dd=%date:~-10,2%
set newdate=%dd%%mm%%yy%
echo %newdate%
I've captured the date, and it prints exactly what I need, but now I need to append the time to the variable. How would I do it?
#ECHO OFF
CLS
set yy=%date:~-4%
set dd=%date:~-7,2%
set mm=%date:~-10,2%
set newdate=%dd%%mm%%yy%_%Time:~0,8%
set newdate=%newdate::=%
echo %newdate%
pause
Read the time into a variable first to get a snapshot so that it doesn't keep ticking while you're extracting the fields. Then use the set substring operators to extract what you want.
The time has the format HH:MM:SS.MS (at least in my en-us locale). One gotcha is that the hour field might start with a leading space, so you need an if condition to change it to a leading zero or to remove the space.
set "current_time=%time%"
set "hour=%current_time:~0,2%"
if "%current_time:~0,1%"==" " set "hour=0%current_time:~1,1%"
set "min=%current_time:~3,2%"
set "sec=%current_time:~6,2%"
set "ms=%current_time:~-2%"
set "newtime=%hour% %min% %sec% %ms%"
echo %newtime%
If you want to remove the front space in the hour instead of changing it to a leading zero, then you'd do this instead:
set "hour=%current_time:~0,2%"
if "%current_time:~0,1%"==" " set "hour=%current_time:~1,1%"
This worked for me:
CLS
#ECHO OFF
set yy=%date:~-4%
set mm=%date:~-7,2%
set dd=%date:~-10,2%
set newdate=%dd%%mm%%yy% & time /T
echo %newdate%
pause
You can run multiple commands by adding the & symbol. If you wish to only append time, if the first command suceed, use && instead.
In this qustion, Save and Load .bat game I used Mat's answer.
But now I have a problem with "saving" numbers using said answer.
If the variable is not double digits (for example 1 or 0) it will "save" the variable as " " and thus will crash the game whenever you do anything that needs that variable. The game sets the variable fine before that.
For example if I pick up the rag, then type Inv, it will say I'm holding the rag. If I then save and load again, then type Inv, it wont say I'm holding anything!
It also won't echo "Nothing" which it should do if %raghave% = 00
(I also have the save file open in Notepad++ and so can see that set RagHave=)
(Also if I use Mat's code with the spaces, then the variable is set as "set RagHave=1" and so adds a space at the end)
The problem is Mat's solution!
For better understanding I repeat his solution
#echo #ECHO OFF > savegame.cmd
#echo SET ITEMS=%ITEMS% >> savegame.cmd
#echo SET HEALTH=%HEALTH% >> savegame.cmd
#echo SET MONEY=%MONEY% >> savegame.cmd
In my opinion, it has multiple disadvantages.
The # prefix isn't necessaray.
The redirection is repeated for each line (I don't like redundancy).
It needs the spaces, as without spaces you got problems with numbers.
Sample with items=1
#echo set ITEMS=1>>savegame.cmd
This results not in writeing set items=1 it writes set items= to 1>>savegame.cmd 1>> is the standard stream.
You can solve all problems with
(
echo #ECHO OFF
echo SET "ITEMS=%ITEMS%"
echo SET "HEALTH=%HEALTH%"
echo SET "MONEY=%MONEY%"
) > savegame.cmd
The quotes are used to ensure that "hidden" spaces after the set are ignored.
Btw. It's a bad idea to use a construct like if %raghave% = 00, (you need two equal signs), as 00 isn't a normal number you can't count or calculate with it, it's better to use 0 instead.
Then also this should work
set /a items=0
set /a items=items+1
set /a items=items-1
if %items%==0 echo There are no items
I have a batch script use to display a list of files's modified date & time.
This is the script's code :
for %%v in (*.html) do (
echo %%~tv
)
Question is, how do I parse the result into two variables. Each for date and time consecutively.
Please advice.
Regards,
Dino
If I were to solve such a problem for myself, I would do the following:
I would run that script of yours to see what output it produces. To be honest, I have run that script, and here's what I've got:
12/15/2009 08:54 AM
12/15/2009 09:30 AM
05/31/2011 07:35 PM
12/02/2009 05:53 PM
12/19/2009 09:33 PM
04/10/2010 02:07 PM
11/23/2010 03:21 PM
01/06/2010 12:03 PM
My next step then would be to determine (visually) what part of every string is the date and what part is the time, I mean, what position the substrings start at and what their lengths are.
In my case it appears to be... (where's my ruler?)
1 1
0 5 0 5
||||||||||||||||||||
04/10/2010 02:07 PM
Ah yes, position 0, length 10 for the date and position 11, length 8 for the time. (As you can see, for strings in batch scripts I have a special ruler that starts from 0.)
Now that I know where to locate the date and the time in the output, I can extract them accordingly. But first I'd need a variable for the whole string, because extracting is applied to environment variables, not loop variables. Here:
SETLOCAL EnableDelayedExpansion
FOR %%v IN (*.html) DO (
SET datetime=%%~tv
ECHO !datetime:~0,10!
ECHO !datetime:~11,8!
)
ENDLOCAL
You might have noticed that apart from introducing a variable I also added enabling delayed expansion (of variables). This is necessary, because with the immediate expansion, i.e. like this:
FOR %%v IN (*.html) DO (
SET datetime=%%~tv
ECHO %datetime:~0,10%
ECHO %datetime:~11,8%
)
it wouldn't work. The thing is, the %datetime:…% expressions would be evaluated before the loop was invoked, and thus would produce empty strings. (This peculiarity of behaviour applies to all cases where you have a bunch of commands in parentheses, whether it is a FOR loop, an IF or IF..ELSE command, or even simply a redirection applied to a set of commands, like >file (commands).)
Instead of just outputting the values you could store them in other variables to process later in the loop body:
SETLOCAL EnableDelayedExpansion
FOR %%v IN (*.html) DO (
SET datetime=%%~tv
SET fdate=!datetime:~0,10!
SET ftime=!datetime:~11,8!
:: now do whatever you like with !fdate! and !ftime!
…
)
ENDLOCAL