UserASR
UserASR

Reputation: 2205

Extract leading numbers from a string in batch script

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, 234.healthy, 3456wealthy etc.

I want to extract the leading numbers from each string. the only pattern here is that all these strings contain numbers in the beginning.

I can't use echo %str:~0,3% as it doesn't fulfill my requirement.

Upvotes: 6

Views: 7954

Answers (6)

aschipfl
aschipfl

Reputation: 34899

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.

Upvotes: 1

Aacini
Aacini

Reputation: 67216

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%

Upvotes: 12

npocmaka
npocmaka

Reputation: 57252

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%

Upvotes: 7

MC ND
MC ND

Reputation: 70923

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

Upvotes: 7

Klitos Kyriacou
Klitos Kyriacou

Reputation: 11621

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%

Upvotes: 2

Jean-François Fabre
Jean-François Fabre

Reputation: 140168

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

Upvotes: 4

Related Questions