批处理文件,如果字符串以

Squ*_*red 2 batch-file

我需要知道一个字符串是否以某东西开头,产生了这个小例子来解释(我使用批处理编译器/预处理器或带有高级命令的任何东西):

rem GetInput
if "%result%"=="cd *" goto Cd
:Cd
if "%result%"=="cd meow" Echo Going to directory 'meow'...
Run Code Online (Sandbox Code Playgroud)

但是此代码不起作用,如果字符串%result%以字母cd开头,则在带有“ cd *”的行中,脚本不会转到:Cd。不知道我现在是否真的可以理解,但愿意帮忙x)

谢谢,

-广场

Wes*_*son 6

如果我正确理解这一点,则您正在尝试确定该值是否%result%以'cd'开头,并且您未成功使用a *作为通配符来确定这一点。

有几种不同的方法可以解决此问题。这是一种方法:您可以检查前两个字符是否等于'cd':

if /i "%result:~0,2%"=="cd" goto Cd
Run Code Online (Sandbox Code Playgroud)

set /? 对此有更多了解。


ruf*_*fin 5

标题比用例更广泛,这使得通用的startsWith对于特定问题来说有点矫枉过正——正如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
Run Code Online (Sandbox Code Playgroud)

更容易阅读的重构?(TL;DR——这就是答案)

这似乎可行,但它并没有真正返回值,而且它的变量名称非常 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
Run Code Online (Sandbox Code Playgroud)

这将返回一个1in%errorlevel%表示“是”,“does-start-with”,以及“ 0no”,“does-NOT-start-with”。您可能会争辩说 does-start-with 应该返回0“无错误”。如果您有强烈的感觉,显然欢迎您在实现中交换这些内​​容。我会选择“零传统上是假的,因此它代表错误的返回值”。嗯,

测试实施

这是一个完整的测试示例......

@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
Run Code Online (Sandbox Code Playgroud)

输出

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
Run Code Online (Sandbox Code Playgroud)

这是一个巧妙的技巧。它基本上...

  1. 创建一个以以下开头的新字符串needle
  2. 如果needle出现在 中的任何位置,则将出现在 出现之后haystack的部分添加到新字符串中。否则将所有添加到新字符串中。haystickneedlehaystack
  3. 如果这个新字符串匹配haystack,你就赢了!否则你就输了。

因此,如果needle是slap并且haystack是slappy%s%则将slap加上[slap其中后面的所有内容slappy都是...] py。这给了我们slappy,它与 中的内容相匹配haystack,我们赢了。

如果 Needle 是spam, haystack 是slappy%s%将从 开始spam,然后,因为spam不在 中,所以slappy我们添加所有haystack。这让我们留下了spamslappy,我们也失去了。(spamslappy?这就是喜剧。)

当您查找位于 不在 开头的内容时haystack,就像我们的示例一样,就会失败lap。也就是说,如果针是 ,lap干草堆是slappy%s%将从 开始,然后,从inlap结尾开始的所有内容也给出,我们有加号或,但不是,我们再次失败,但以一种新的、很酷的方式。lapslappypylappylappyslappy


您的批处理语法问题已得到解答(也许)

波浪号是什么set "needle2=%~2"

参数引用删除。命令行参数之前的波浪号(例如"%~1")表示从参数中删除周围的引号。如果 的值%1"Hi"那么%~1将扩展到仅Hi

call set "s=%str%%%txt:*%str%=%%"有点复杂。

首先了解冒号(:)意味着我们正在使用“字符串替换功能”:

此代码取自同一页面,替换needshasin %str

set str=%str:needs=has% 
echo %str%
Run Code Online (Sandbox Code Playgroud)

那么我们需要知道...

“StrToFind”[在:]之后可以以星号开头,在这种情况下,它将替换“StrToFind”左侧的所有字符。
...

::Delete the character string 'ab' and everything before it
SET _test=12345abcabc
SET _result=%_test:*ab=% 
ECHO %_result%          =cabc
Run Code Online (Sandbox Code Playgroud)

然后看这个答案

那里call会导致另一层变量扩展,因此有必要[转义]原始%符号,但最终一切都会解决。

现在call set "s=%str%%%txt:*%str%=%%"应该有道理了。

该问题的另一个答案表明,DOSTips 中的startsWith 方法比此处的其他答案稍微不那么挑剔,因为......

您可以使用 !,但必须设置 ENABLEDELAYEDEXPANSION 开关。

我们正在避免这种情况。

最后...

如果您对所有这些神秘规则的疯狂感到震惊,那么您应该学习 PowerShell,它太棒了!

哈!好的,但我们仍然可以在不离开批次的情况下完成它。享受!