I am new to batch scripting. although i have shell and python solutions for this problem but got stuck in batch script.
I have string like 123_happy
,
I prefer Jean-François's answer, but the following is an alternative, hacky way of doing it. It relies on testing for success or failure of the set /a
command. We test increasingly longer starting parts of the string until we fail, and then we know the previous attempt was the right one.
@echo off
rem Prints the numbers in front of a string variable.
rem IMPORTANT - this batch file must have a .cmd extension (NOT a .bat)
setlocal enabledelayedexpansion
call :getnumbers 123_happy
call :getnumbers 234.healthy
call :getnumbers 3456wealthy
exit /b
:getnumbers
set s=%1
for /l %%i in (1 1 999) do (
set substr=!s:~0,%%i!
set /a n=!substr! 2>nul
if errorlevel 1 goto :getnumbers_exitloop
)
:getnumbers_exitloop
echo The number in front of %1 is %n%
What about this:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define the string here:
set "STR=123_happy"
setlocal EnableDelayedExpansion
rem // Get first character behind the numeric part:
for /F delims^=0123456789^ tokens^=*^ eol^= %%F in ("!STR!") do (
endlocal
set "SEP=%%F"
setlocal EnableDelayedExpansion
if defined SEP set "SEP=!SEP:~,1!"
)
rem // Split the string at the character behind the numeric part:
if not defined SEP goto :SKIP
for /F eol^=^%SEP%^ delims^=^%SEP% %%N in ("0!STR!") do (
endlocal
set "STR=%%N"
setlocal EnableDelayedExpansion
set "STR=!STR:~1!"
)
:SKIP
rem // Return the numeric part:
echo(!STR!
endlocal
endlocal
exit /B
The basic idea is to get the first character after the numeric part, which is the used as the delimiter for a for /F
loop parsing the input string. This has got the great advantage that the limit for signed 32-bit integers does not apply, opposed to the approaches using set /A
or for /L
. In addition, leading zeros do not lead to unintentional interpretation as octal numbers, since this script treats the numeric part as string.
Loop (1=>1000 should be enough ;)) on the characters of the variable and find the first char not in number range. Extract the substring before:
@echo off
set z=123_happy
setlocal enabledelayedexpansion
set result=
for /L %%i in (0,1,1000) do (
set zz=!z:~%%i,1!
if x!zz!==x exit /b
if !zz! lss 0 (
set result=!z:~,%%i!
goto out
)
if !zz! gtr 9 (
set result=!z:~,%%i!
goto out
)
)
:out
echo result=!result!
result:
result=123
I think this is the simplest way:
@echo off
setlocal
set "str=123_happy"
set /A num=str
echo Result = %num%
When set /A
command get a value from a variable, it convert the number until the first non-digit character with no error.
To preserve left zeros:
set "str=0128_happy"
set "num=1%str%"
set /A num=num
set "num=%num:~1%"
echo Result = %num%
Just another option
@echo off
setlocal enableextensions disabledelayedexpansion
call :extractLeadingNumbers 123_happy leadingNumbers
echo %leadingNumbers%
call :extractLeadingNumbers 234.healthy leadingNumbers
echo %leadingNumbers%
call :extractLeadingNumbers "3456wealthy" leadingNumbers
echo %leadingNumbers%
goto :eof
rem This extracts the first numerical serie in the input string
:extractLeadingNumbers inputString returnVar
setlocal enableextensions disabledelayedexpansion
rem Retrieve the string from arguments
set "string=%~1"
rem Use numbers as delimiters (so they are removed) to retrieve the rest of the string
for /f "tokens=1-2 delims=0123456789 " %%a in ("%string:^"=%") do set "delimiters=%%a%%b"
rem Use the retrieved characters as delimiters to retrieve the first numerical serie
for /f "delims=%delimiters% " %%a in ("%string:^"=%") do set "numbers=%%a"
rem Return the found data to caller and leave
endlocal & set "%~2=%numbers%"
goto :eof
probably the easiest and the fastest way:
set z=123_happy
for /l %%# in (%z%,1,%z%) do echo %%#
this will leave only the leading numbers.Though it is limited to 32b integers. As a subroutine (will fail if the input contains delimiters):
:extractLeadingNumbers input [rtrnVar]
for /l %%# in (%~1;1;%~1) do (
if "%~2" neq "" (
set "%%#=%~2"
) else (
echo %%#
)
)
More robust way (which will also remove leading zeroes):
cmd /c exit /b 123_happy
echo %errorlevel%