簡體   English   中英

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

[英]Batch file if string starts with

我試圖弄清楚字符串是否以 substring 開頭:

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 /? 有更多關於這個。

標題比用例更廣泛,這使得通用 startsWith 對於特定問題有點矯枉過正——正如 Wes 所說,對於這個特定問題,您可以只檢查前兩個字符並檢查cd

但請記住這一點,讓我們回答標題中更籠統的問題。

一個通用的 startsWith

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

一個更容易閱讀的重構? (TL;DR——這就是答案)

這似乎可行,但它並沒有真正返回一個值,而且它的變量名非常 1990 年代。

我破解了這個:

: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

這將在%errorlevel%中返回1表示是,does-start-with, 0表示否,does-NOT-start-with。 您可能會爭辯說 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

Output

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

這是一個巧妙的技巧。 它基本上...

  1. 創建一個以needle開頭的新字符串
  2. 如果needle出現在haystack中的任何位置haystickneedle出現后出現的部分添加到新字符串中。 否則將所有haystack添加到您的新字符串中。
  3. 如果這個新字符串匹配haystack ,你就贏了。 否則你輸了。

因此,如果 needle 是slap並且 haystack 是slappy ,則%s%將是slap plus [ slap之后的slappy內容是...] py 這給了我們slappy ,它與haystack中的內容相匹配,我們贏了。

如果 needle 是spam而 haystack 是slappy%s%將從spam開始,然后,由於spam不在slappy中,我們添加所有haystack 這給我們留下了spamslappy ,我們輸了。 spamslappy這就是喜劇。)

一個巧妙的失敗是當你尋找一些在大海撈針中不在haystack開始處的東西時,就像在我們的lap示例中一樣。 也就是說,如果 needle 是lap而 haystack 是slappy%s%將從lap開始,然后,從lap in slappy結束的所有內容也給出py ,我們有lappylappy ,這不是slappy ,並且我們又輸了,但以一種新的、很酷的方式。


您的批處理語法問題得到了回答(也許)

set "needle2=%~2"中的波浪號是什么

參數引用刪除。 命令行參數(例如"%~1" )前的波浪號表示從參數中刪除周圍的引號。 這樣,如果%1的值為"Hi" ,則%~1將擴展為僅Hi

call set "s=%str%%%txt:*%str%=%%"有點復雜。

首先了解冒號 ( :表示我們正在使用“ 字符串替換功能”:

此代碼取自同一頁面,用%str中的has替換了needs

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 方法比這里的其他答案要少一些 finnicky,因為......

您可以使用,。 但您必須設置 ENABLEDELAYEDEXPANSION 開關。

我們正在避免這種情況。

而且,最后...

如果你對所有這些神秘規則的瘋狂感到震驚,你應該學習 PowerShell,太棒了!

哈,好的。 但我們仍然可以在不離開批次的情況下完成它。 享受!

這是一個相對強大且通用的startsWith子例程(有兩個示例)。如果字符串以另一個字符串開頭,則將 errorlevel 設置為 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
    )
)
::::::::::::::::::::::::::::::::::::::::::::::::::

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM