我试图弄清楚字符串是否以子字符串开头:
rem GetInput
if "%result%"=="cd *" goto Cd
:Cd
if "%result%"=="cd meow" Echo Going to directory 'meow'...
不幸的是,这并没有在应该循环回到 :Cd 的时候。如何检测字符串是否以
cd
开头?
如果我理解正确的话,您正在尝试确定
%result%
的值是否以“cd”开头,并且您无法成功使用 *
作为通配符来确定这一点。
有几种不同的方法可以处理这个问题。这是一种方法:您可以检查前两个字符是否等于“cd”:
if /i "%result:~0,2%"=="cd" goto Cd
set /?
有更多相关内容。
标题比用例更广泛,这使得通用的starts对于特定问题来说有点矫枉过正——正如Wes所说,对于这个特定问题,你可以只检查前两个字符并检查
cd
.
但是请记住这一点,让我们回答标题中更通用的问题。
DOSTips.com的startsWith解决方案看起来相当不错。
:StartsWith text string -- Tests if a text starts with a given string
:: -- [IN] text - text to be searched
:: -- [IN] string - string to be tested for
:$created 20080320 :$changed 20080320 :$categories StringOperation,Condition
:$source https://www.dostips.com
SETLOCAL
set "txt=%~1"
set "str=%~2"
if defined str call set "s=%str%%%txt:*%str%=%%"
if /i "%txt%" NEQ "%s%" set=2>NUL
EXIT /b
这似乎可行,但它并没有真正返回值,而且它的变量名称非常 20 世纪 90 年代。
我破解了这个:
:startsWith
set "haystack1=%~1"
set "needle2=%~2"
if defined needle2 call set "s=%needle2%%%haystack1:*%needle2%=%%"
if /i "%haystack1%" NEQ "%s%" (
exit /b 0
)
EXIT /b 1
这将在
1
中返回 %errorlevel%
表示“是”、“开始于”,以及 0
表示“否”、“不开始于”。你可能会认为 does-start-with 应该返回 0
来表示“没有错误”。如果您有强烈的感觉,显然欢迎您在实现中交换这些内容。我会选择“零传统上是假的,因此它代表错误的返回值”。 YMMV,🍅🍅。
这是一个完整的测试示例...
@ECHO OFF
call :startsWith slappy slap
echo %errorlevel%
echo.
call :startsWith slap slappy
echo %errorlevel%
echo.
call :startsWith slappy spam
echo %errorlevel%
echo.
call :startsWith slappy lap
echo %errorlevel%
echo.
call :startsWith spam
echo %errorlevel%
echo.
exit /b 0
:startsWith
set "haystack1=%~1"
set "needle2=%~2"
set "s="
REM I think this is okay b/c if %2 was defined, %1 kinda has to be too.
if defined needle2 call set "s=%needle2%%%haystack1:*%needle2%=%%"
echo needle: %needle2%
echo haystack: %haystack1%
echo s: %s%
if /i "%haystack1%" NEQ "%s%" (
exit /b 0
)
EXIT /b 1
needle: slap
haystack: slappy
s: slappy
1
needle: slappy
haystack: slap
s: slappyslap
0
needle: spam
haystack: slappy
s: spamslappy
0
needle: lap
haystack: slappy
s: lappy
0
needle:
haystack: spam
s:
0
这是一个巧妙的技巧。基本上...
needle
needle
出现在 haystack
中的 anywhere,请将
haystick
出现在 needle
之后出现的部分添加到新字符串中。否则将所有 haystack
添加到新字符串中。haystack
匹配,你就赢了!不然你就输了因此,如果针是
slap
,干草堆是slappy
,那么%s%
将是slap
加上[slap
中slappy
之后的所有内容,即...]py
。这给了我们 slappy
,它与 haystack
中的内容相匹配,我们赢了。
如果针是
spam
并且干草堆是slappy
,%s%
将从spam
开始,然后,由于spam
不在slappy
中,我们添加haystack
的all。这让我们只剩下
spamslappy
,我们就输了。 (spamslappy
?现在这是喜剧。)
当你寻找 is in 但 not 位于
haystack
开头的东西时,就像我们的 lap
示例一样,这是一个彻底的失败。也就是说,如果针是lap
并且干草堆是slappy
,%s%
将以lap
开始,然后,从lap
中slappy
结束的所有内容也给出py
,我们有 lap
加上py
或lappy
,这不是slappy
,我们再次失败,但以一种新的、很酷的方式。
set "needle2=%~2"
中的波形符是什么?
删除参数引用。命令行参数之前的波浪号(例如
)表示从参数中删除周围的引号。例如,如果"%~1"
的值为%1
,则"Hi"
将扩展到仅%~1
。Hi
call set "s=%str%%%txt:*%str%=%%"
有点复杂。
首先了解冒号(
:
)意味着我们正在使用“字符串替换功能”:
此代码取自同一页面,将
needs
中的has
替换为%str
:
set str=%str:needs=has%
echo %str%
然后我们需要知道...
“StrToFind”[在
之后]可以以星号开头,在这种情况下,它将替换“StrToFind”左侧的所有字符。:
...::Delete the character string 'ab' and everything before it SET _test=12345abcabc SET _result=%_test:*ab=% ECHO %_result% =cabc
那就看这个答案:
那里的
导致了另一层变量扩展,因此有必要[转义]原始的call
符号,但最终一切都会解决。%
现在
call set "s=%str%%%txt:*%str%=%%"
应该有意义了。
该问题的另一个答案表明,DOSTips 中的startsWith 方法比这里的其他答案稍微不那么挑剔......
您可以使用 !,但您必须设置 ENABLEDELAYEDEXPANSION 开关。
我们正在避免这种情况。
然后,最后...
如果您对所有这些神秘规则的疯狂感到震惊,那么您应该学习 PowerShell,这太棒了!
哈! 😏 好的,但是我们仍然可以在不离开批次的情况下完成它。享受吧!
这里有一个相对稳健且通用的
startsWith
子例程(有两个示例)。如果字符串以另一个字符串开头,它将错误级别设置为1,如果不是,则将错误级别设置为0。
@echo off
set string1=abc123123
set checker1=abc
call :startsWith %string1% %checker1%
if %errorlevel% equ 1 (
echo %string1% starts with %checker1%
) else (
echo %string1% does NOT start with %checker1%
)
set string2=xyz123123 abc
call :startsWith %string2% %checker2%
if %errorlevel% equ 1 (
echo %string2% starts with %checker2%
) else (
echo %string2% does NOT start with %checker2%
)
exit /b 0
::::::::::::::::::::::::::::::::::::::::
:::----- subroutine starts here ----::::
:startsWith [%1 - string to be checked;%2 - string for checking ]
@echo off
rem :: sets errorlevel to 1 if %1 starts with %2 else sets errorlevel to 0
setlocal EnableDelayedExpansion
set "string=%~1"
set "checker=%~2"
rem set "var=!string:%~2=&echo.!"
set LF=^
rem ** Two empty lines are required
rem echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!checker!") do (
rem set "var=!string:%%~R%%~R=%%~L!"
set "var=!string:%%~R=#%%L!"
)
)
for /f "delims=" %%P in (""!var!"") DO (
if "%%~P" EQU "#" (
endlocal & exit /b 1
) else (
endlocal & exit /b 0
)
)
::::::::::::::::::::::::::::::::::::::::::::::::::
我找到了一个更简单的答案。
set result=cd meow
echo %result%|>nul findstr /b /l "cd "
if %ERRORLEVEL% EQU 0 (echo success) else (echo fail)
您还可以使用
/e
标志检查渲染器。正则表达式也带有 /r
。
警告:
findstr
很慢。最好不要经常打电话。