Extract leading numbers from a string in batch script

后端 未结 6 1612
灰色年华
灰色年华 2021-01-02 23:39

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,

相关标签:
6条回答
  • 2021-01-03 00:01

    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%
    
    0 讨论(0)
  • 2021-01-03 00:04

    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.

    0 讨论(0)
  • 2021-01-03 00:11

    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
    
    0 讨论(0)
  • 2021-01-03 00:12

    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%
    
    0 讨论(0)
  • 2021-01-03 00:20

    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
    
    0 讨论(0)
  • 2021-01-03 00:25

    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%
    
    0 讨论(0)
提交回复
热议问题