I have multiple strings that are in the following format:
"At Revision ###."
Where ### can be one, two, three, or four digits long.
How do I parse that string in cmd to only grab the number?
try this (cmd shell script):
set "string=At Revision ###."
for /f "tokens=3delims=. " %%i in ("%string%") do set "number=%%i"
echo(%number%
Related
I am making a batch program that needs to take this line in a .txt file:
Random Characters: 93h4-283ed-93j2-je82
and take ONLY the 93h4-283ed-93j2-je82 and put it into a variable. (its the first line in a txt file)
How can I do this? I have looked around on the interwebs but most of the answers I found didn't work the way I wanted.
I looked around on Stack Overflow and other sources but they made the entire line disappear if it contained some words, whereas I only want to take a piece of the line and put it into a batch variable/string.
text.txt
Random Characters: 93h4-283ed-93j2-je82
textf.txt should be
93h4-283ed-93j2-je82
Based purely on what you've provided, i.e. Split the first line of text.txt keeping everything after the first sequence of the two characters, : and output to textf.txt.
#<"text.txt" (Set/P "Var="&Call Echo(%%Var:*: =%%)>"textf.txt"
If you're just looking to grab Random Characters as a string, This can be done very easy in an for loop. We use type text.txt to get the file displayed line by line to a variable. From there we look for lines containing Random Characters: by using find /I "Random Characters:". Finally we can extract the Numbers by using "tokens=1-2,3* delims= " inside the for loop.
Rem | Get .txt To String
FOR /F "tokens=*" %%A IN ('type text.txt') DO (
Rem | Find The First "Random Characters" Line
for /f "tokens=1-2,3* delims= " %%B in ('echo %%A^| find /I "Random Characters:"') do (
Rem | Set String
Set "String=%%D"
Rem | Break Loop
Goto Finished
)
)
:Finished
Echo %String%
If you're looking to update an text file and remove the Random Characters: then we can add a replace function to edit the text file.
#ECHO OFF
#setlocal EnableDelayedExpansion
Rem | Configuration
Set "FileLocation=text.txt"
Rem | Get .txt To String
FOR /F "tokens=*" %%A IN ('type !FileLocation!') DO (
Rem | Find The First "Random Characters" Line
for /f "tokens=1-2,3* delims= " %%B in ('echo %%A^| find /I "Random Characters:"') do (
Rem | Set SearchText & ReplaceText
Set "SearchText=%%A"
Set "ReplaceText=%%D"
Rem | Break Loop
Goto EditString
)
)
goto :EOF
:EditString
REM | Make sure we only edit the Random Characters: line.
FOR /F "delims=" %%n IN ('findstr /n "^" %FileLocation%') DO (
SET line=%%n
SET Modified=!line:%SearchText%=%ReplaceText%!
SET Modified=!Modified:*:=!
REM | Output the entire edited INI to a temporary file.
>> %FileLocation%.TEMP ECHO(!Modified!
)
Rem | Delete Original File, Restore New
DEL %FileLocation%
REN %FileLocation%.TEMP %FileLocation%
Goto :EOF
Input Raw Text File:
Random Characters: 93h4-283ed-93j2-je82
Random Characters: 93i4-283ed-93j2-je82
Hello My Name John
Random Characters: 93j4-283ed-93j2-je82
Nice To Meet You
Random Characters: 93k4-283ed-93j2-je82
How Is Your Day
Random Characters: 93l4-283ed-93j2-je82
Output Raw Text File:
93h4-283ed-93j2-je82
Random Characters: 93i4-283ed-93j2-je82
Hello My Name John
Random Characters: 93j4-283ed-93j2-je82
Nice To Meet You
Random Characters: 93k4-283ed-93j2-je82
How Is Your Day
Random Characters: 93l4-283ed-93j2-je82
Keep in mind I have left Rem comments for each process of the script. For any more help on the commands, type the following into a command prompt:
set /?
for /?
if /?
goto /?
Exc.
I want to make an action in a batch file dependent on my free storage space, but it fails (interestingly only sometimes), because the free space is more than 2GB, making the variable not settable.
This is the batch file:
cd "C:\Users\Fabian\Desktop\Screen Recordings\Auto"
for /F "usebackq delims== tokens=2" %%x in (`wmic logicaldisk where "DeviceID='C:'" get FreeSpace /format:value`) do (set FreeSpace=%%x)
if (%FreeSpace%) LSS (2499522027520) (
for /F "delims=" %%a in ('dir /b /a-d /t:w /o:d "C:\Users\Fabian\Desktop\Screen Recordings\Auto\*.flv"') do (
del "%%a"
goto :breakLoop
))
:breakLoop
exit
A lot of this is just workarounds for Windows' weirdnesses, the important part is: set FreeSpace=%%x
That x is a string straight out of the live disk data, which should be converted to a number, but since it's bigger than 232, that fails (and it makes it a string, making the comparison in the next line a string comparison, which is not at all what I want).
I can also not divide it by a number, because that would require it being a number first.
Would I have to use the gross hack of chopping off digits at the end by changing the length of the string (if yes, how?) or is there a way to have proper long numbers in a batch file?
I found this script (archive) that actually works, but I don't know how. Which part of it chops off the digits and which is the important part that I need? I can't let it sum up all folder sizes every time, because the script runs every 20 seconds.
It is not possible in Windows command prompt to handle numbers outside of the range of signed 32-bit integers which range from -231 = -2147483648 to 231 - 1 = 2147483647.
You could however remove a couple of digits using sub-string expansion, say 6, on the right to have a rounded-down number of Mega-Bytes instead of Bytes and use the result for a numeric comparison, like this:
cd "%USERPROFILE%\Desktop\Screen Recordings\Auto"
set "FreeSpace=0"
for /F "usebackq skip=1" %%x in (`wmic logicaldisk where "DeviceID='C:'" get FreeSpace^,Size`) do (set "FreeSpace=%%x")
rem // Remove the last 6 digits to get MBytes:
set "FreeSpaceMB=%FreeSpace:~,-6%"
rem // Ensure to not leave an empty value behind:
if not defined FreeSpaceMB set "FreeSpaceMB=0"
if %FreeSpaceMB% LSS 2499522 (
for /F "delims=" %%a in ('dir /B /A:-D /T:W /O:D "C:\Users\Fabian\Desktop\Screen Recordings\Auto\*.flv"') do (
del "%%a"
goto :breakLoop
)
)
:breakLoop
exit /B
Of course you lose precision but this could probably be acceptable for the purpose at hand.
I also changed the for /F loop that captures the wmic output in order to avoid Unicode conversion artefacts like orphaned carriage-return (CR) characters, which would result in the variable FreeSpace to contain a number plus a CR. That is why I queried also the value Size although it is not needed, but so the FreeSpace value is not the last one which might be tailed by a CR.
By the way, note that I removed the superfluous parentheses from the if command line.
I am trying to split the entries in text files, which are in the format:
"C:\Software\New folder\New folder\New folder\New folder\OneDrive - Test "
"C:\Software\New folder\New folder\New folder\New folder\OneDrive - Test "
"C:\Software\New folder\New folder\New folder\New folder\OneDrive - Test "
using quotes to show the spaces in the code above. In simple words, my text always ends with two spaces or more.
So I want to delimiter to be , (yes two spaces) so my final output should be
"C:\Software\New folder\New folder\New folder\New folder\OneDrive - Test"
using quotes to show the spaces
Alternatively, I also know that the final words in the string are always One Drive - Test
And even if I could split the output in the format below, I could then append to each line with One Drive - Test
"C:\Software\New folder\New folder\New folder\New folder"
Thank you guys, really getting tired of Batch.
If all your lines follow the shown pattern then, instead of trying to deal with strings, you can deal with file references
#echo off
setlocal enableextensions disabledelayedexpansion
rem For each line in input file
for /f "usebackq delims=" %%a in ("inputFile.txt") do (
rem Retrieve the parent folder of the read reference
for %%b in ("%%~dpa.") do (
rem And echo it without the ending backslash (see the dot in the upper line)
echo %%~fb
)
)
%%a will hold each of the read lines while iterating over the input file
%%~dpa is the drive and path of the element referenced in %%a with an ending backslash
By adding a . to the previous path and retrieving its full path, we remove the ending backslash (unless the path is the root of a drive)
To save the processed lines, you only need to redirect the output
#echo off
setlocal enableextensions disabledelayedexpansion
>"outputFile.txt" (
for /f "usebackq delims=" %%a in ("inputFile.txt") do (
for %%b in ("%%~dpa.") do echo %%~fb
)
)
There is the for /F loop to split strings at a certain delimiter character. Since you have two characters that mark a single delimiter (namely two SPACEs), you could replace these by a single character that cannot occur elsewhere in the string; for example, the | could be used as it is not allowed in file paths/names. This is how it may look like:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Read input text file `txtfile.txt` line by line:
for /F "usebackq delims= eol=|" %%L in ("textfile.txt") do (
rem // Store line string in environment variable:
set "LINE=%%L"
rem // Toggle delayed expansion to avoid loss of/trouble with exclamation marks:
setlocal EnableDelayedExpansion
rem /* Replace two-character delimiter by a single character:
rem (the `|| endlocal` suffix is only executed in case the current line contains
rem delimiters only, because the `for /F` loop would not execute in that case) */
(for /F "delims=| eol=|" %%F in ("!LINE: =|!") do (
rem // Toggle back delayed expansion:
endlocal
rem /* Return part before first delimiter (actually this returns the very first
rem non-empty sub-string before the first (sequence of) delimiter(s), or,
rem if the string begins with (a) delimiter(s), the very first non-empty
rem sub-string between the first and second (sequences of) delimiters: */
echo/%%F
)) || endlocal
)
endlocal
I am trying to get a value from a string that has a left boundary of test/time (ms)= and right boundary of , test/status=0.
For example, if I have an input string that looks like:
input="test/ing=123, hello/world=321, test/time (ms)=100, test/status=0"
In Perl, I know I can do something like:
input=~/"test/time (ms)="(.*)", test/status=0"/;
$time=$1;
$time will hold the value that I want to get.
Unfortunately, I can only write the code in Windows Batch or VBScript. Does anyone know how batch can perform the same action as the one in Perl?
Pure batch:
for /f "delims==," %%A in ("%input:*test/time (ms)=%) do echo %%A
The search and replace within the IN clause looks for the first occurance of test/time (ms) and replaces from the beginning of the original string to the end of the search string with nothing. The FOR /F then parses out the 100 using delimiters of = and ,.
The presence of enclosing quotes within the value of %input% causes the IN() clause to look weird with no visible end quote.
It looks better with delayed expansion:
setlocal enableDelayedExpansion
for /f "delims==," %%A in ("!input:*test/time (ms)=!") do echo %%A
I prefer to keep enclosing quotes out of my variable values, and explicitly add them to my code as needed. This makes the normal expansion version look more natural (delayed expansion version remains same):
set "input=test/ing=123, hello/world=321, test/time (ms)=100, test/status=0"
for /f "delims==," %%A in ("%input:*test/time (ms)=%") do echo %%A
Batch with help of JScript
If you have my hybrid JScript/batch REPL.BAT utility, then you can use regex to be very specific in your parsing:
call repl ".*test/time \(ms\)=(.*?),.*" $1 sa input
To get the value in a variable:
set "val="
for /f "delims=" %%A in ('repl ".*test/time \(ms\)=(.*?),.*" $1 sa input') do set "val=%%A"
Note that CALL is not needed within IN() clause. It also is not needed when using pipes.
Batch file:
SET input="test/ing=123, hello/world=321, test/time (ms)=100, test/status=0"
FOR %%i IN (%input:, =" "%) DO FOR /F "TOKENS=1,* DELIMS==" %%j IN (%%i) DO IF "%%j" == "test/time (ms)" ECHO %%k
EDIT: explanation
%input:, =" "% returns "test/ing=123" "hello/world=321" "test/time (ms)=100" "test/status=0"
Outer FOR will assign %%i to each string from previous result.
Inner FOR will assign characters left of = to %%j, and right ones to %%k.
Then is just comparing %%j with desired key and showing value if match.
VBScript/RegExp:
>> input="test/ing=123, hello/world=321, test/time (ms)=100, test/status=0"
>> set r = New RegExp
>> r.Pattern = "\(ms\)=(\d+),"
>> WScript.Echo r.Execute(input)(0).Submatches(0)
>>
100
I am trying a batch file which replaces a changing text named X by a static text 'English' into the path
Y:\SUT\ISTQB\Board\X\Dashboard\Open
About the position of the X text, it is always surrounded with 'Board' and 'Dashboard'.
In the path below, the current below text for the given path is 'X=Language' and my goal is finally to get 'X=English' each time of course!
Y:\SUT\ISTQB\Board\Language\Dashboard\Open
The string of replacement is read from a file. This file only contains 'English'
Is that possible to find a solution through a pipe with the 'find' command?
Thank you in advance
#ECHO OFF
SETLOCAL
SET mypath=Y:\SUT\ISTQB\Board\X\Dashboard\Open
FOR /f %%i IN (languagefile.txt) DO SET language=%%i
SET mypath=%mypath:\Dashboard\=*%
SET mypath=%mypath:\Board\=*%
FOR /f "tokens=1,3delims=*" %%i IN ("%mypath%") DO SET mypath=%%i\Board\%language%\Dashboard\%%j
ECHO %mypath%
"*" chosen because it cannot occur in a pathname.
Try this:
#echo off &setlocal enabledelayedexpansion
set "string=Y:\SUT\ISTQB\Board\Language\Dashboard\Open"
set "search=%string:*\Board\=%"
for /f "delims=\" %%i in ("%search%") do set "search=%%i"
set "string=!string:%search%=English!"
echo %string%