我是批处理脚本的新手。虽然我有解决这个问题的shell和python解决方案,但却陷入批处理脚本。
我有123_happy
,234.healthy
,3456wealthy
等字符串。
我想从每个字符串中提取前导数字。这里唯一的模式是所有这些字符串都包含数字。
我不能使用echo %str:~0,3%
,因为它不符合我的要求。
答案 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 /A
或for /L
的方法相比,这具有很大的优势,即有符号32位整数的限制不适用。此外,前导零不会导致无意解释为八进制数,因为此脚本将数字部分视为字符串。