从批处理脚本中的字符串中提取前导数字

时间:2016-09-17 08:39:20

标签: batch-file cmd

我是批处理脚本的新手。虽然我有解决这个问题的shell和python解决方案,但却陷入批处理脚本。

我有123_happy234.healthy3456wealthy等字符串。

我想从每个字符串中提取前导数字。这里唯一的模式是所有这些字符串都包含数字。

我不能使用echo %str:~0,3%,因为它不符合我的要求。

6 个答案:

答案 0 :(得分:11)

我认为这是最简单的方法:

@echo off
setlocal

set "str=123_happy"
set /A num=str
echo Result = %num%

set /A命令从变量获取值时,它会将数字转换为第一个非数字字符而没有错误。

保留左零:

set "str=0128_happy"
set "num=1%str%"
set /A num=num
set "num=%num:~1%"
echo Result = %num%

答案 1 :(得分:7)

只是另一种选择

@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

答案 2 :(得分:7)

可能是最简单,最快捷的方式:

set z=123_happy
for /l %%# in (%z%,1,%z%) do echo %%#

这将只留下前导数字。尽管它仅限于32b整数。 作为子例程(如果输入包含分隔符,则会失败):

:extractLeadingNumbers input [rtrnVar]
  for /l %%# in (%~1;1;%~1) do (
     if "%~2" neq "" (
       set "%%#=%~2"
     ) else (
       echo %%#
     )
  )

更多健壮方式(也会删除前导零):

cmd /c exit /b 123_happy
echo %errorlevel%

答案 3 :(得分:4)

循环(1 => 1000应该足够;))对变量的字符进行查找并找到不在数字范围内的第一个字符。在之前提取子字符串:

@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=123

答案 4 :(得分:2)

我更喜欢Jean-François的回答,但以下是另一种做法的替代方法。它依赖于对set /a命令成功或失败的测试。我们测试字符串的起始部分越来越长,直到我们失败,然后我们才知道之前的尝试是正确的。

@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%

答案 5 :(得分:1)

这个怎么样:

@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

基本思想是获取数字部分之后的第一个字符,它用作解析输入字符串的for /F循环的分隔符。与使用set /Afor /L的方法相比,这具有很大的优势,即有符号32位整数的限制不适用。此外,前导零不会导致无意解释为八进制数,因为此脚本将数字部分视为字符串。