Batch file 如何在Windows命令行或批处理文件中搜索字符串中的斜杠或冒号?

Batch file 如何在Windows命令行或批处理文件中搜索字符串中的斜杠或冒号?,batch-file,cmd,Batch File,Cmd,我正在尝试编写一个函数,该函数接受一个参数并将其分类为文件夹名(文件夹)、相对路径名、或绝对路径名 到目前为止,我得到的是: @echo off call :classifyInput C:\Users\MikeW echo C:\Users\MikeW is of type %_inputType% call :classifyInput documentation echo documentation is of type %_inputType% goto :EOF :classifyI

我正在尝试编写一个函数,该函数接受一个参数并将其分类为文件夹名(
文件夹
)、
相对路径名
、或
绝对路径名

到目前为止,我得到的是:

@echo off
call :classifyInput C:\Users\MikeW
echo C:\Users\MikeW is of type %_inputType%
call :classifyInput documentation
echo documentation is of type %_inputType%
goto :EOF

:classifyInput
SETLOCAL
set _inputType=
rem // a string is a "name of folder" iff it has no '/', '\\' or ':' in it, and a pathname otherwise
echo %1%|findstr /i [\/:] >nul
if %errorlevel% == 1 set _inputType=FOLDER
echo %errorlevel%
rem // a string is a "relative pathname" iff it has no ':' as its second character, and an absolute pathname otherwise
if _inputType == [] & "%1:~2,1% == :" (
    _inputType=ABSOLUTE_PATHNAME
    echo You gave me absolute pathname.
)

ENDLOCAL & set _inputType=%_inputType%
到目前为止,我的函数在这两种情况下的表现是相同的


此外,Google搜索如何查找字符
/
\
没有返回任何有用的结果。

要回答您的问题,用
/
\
findstr
查找字符,您可以使用如下正则表达式:

findstr "[\\/:]"
:classifyInput
SETLOCAL
set _inputType=
set input=%~1

rem // a string is a "name of folder" iff it has no '/', '\\' or ':' in it, and a pathname otherwise
echo %input%|findstr /r "\\\\ / :" >nul
if %errorlevel% == 1 (
    set _inputType=FOLDER
) else (
     if "%input:~1,1%" == ":" (
        set _inputType=ABSOLUTE_PATHNAME
        echo You gave me absolute pathname.
    ) else (
        set _inputType=RELATIVE_PATHNAME
    )
)

ENDLOCAL & set _inputType=%_inputType%
编辑:或者,如果您想在脚本注释中描述的字符串中查找
\\
/
,您可以使用:

findstr /r "\\\\ / :"
由于
\
是正则表达式中的转义字符,因此需要将其自身转义,以获得真正的
\
。 将其正则表达式中的空白用作
运算符

在继续之前,我想指出代码中的一些小错误并帮助您改进:

  • 比较
    \u inputType=[]
    将比较文字字符串“\u inputType”和字符串“[]”。如果要检查变量是否为空,请使用
    If defined var
    ,该变量只有在
    %var%
    不为空时才会变为真(对于相反的行为,使用
    If not
    ),或者如果“%var%==”
,则使用
。但请确保使用相同的分隔符,因为
==
运算符将比较每个单个字符:
如果abc==“abc”
将不会执行,但是
如果“abc”==“abc”
将执行

  • 子字符串提取仅适用于使用
    set
    定义的环境变量。它不适用于参数变量(也不适用于循环变量)。所以
    %1:~2,1%
    不会得到你想要的。它将用其中参数的值替换
    %1
    ,并给出类似
    C:\Users\MikeW:~2,1%
    的内容。如果要从参数中提取,则必须使用参数值设置一个变量,并从该变量中提取:

    set input=%~1
    rem now you can use %input:~2,1%
    
    在您的代码中,我了解到您需要输入的第二个字符:
    %input:~2,1%
    将为您提供第三个字符,而不是第二个字符。如果是子字符串,请将
    %var:~n,k%
    读为第n个字符后的k个字符。因此,您需要的是
    %输入:~1,1%

  • 我假定您试图在此行上执行
    操作:

    if _inputType == [] & "%1:~2,1% == :"
    
    不幸的是,
    以及
    运算符不存在于批处理中,因此您必须通过使用连续的if语句(在应用上述修改后)自己“模拟”

  • 最后我得到了这个:

    @echo off
    call :classifyInput C:\Users\MikeW
    echo C:\Users\MikeW is of type %_inputType%
    call :classifyInput documentation
    echo documentation is of type %_inputType%
    call :classifyInput Documents\Folder\inside
    echo Documents\Folder\inside is of type %_inputType%
    goto :EOF
    
    :classifyInput
    SETLOCAL
    set _inputType=
    set input=%~1
    
    rem // a string is a "name of folder" iff it has no '/', '\\' or ':' in it, and a pathname otherwise
    echo %input%|findstr /r "\\\\ / :" >nul
    if %errorlevel% == 1 set _inputType=FOLDER
    
    echo %errorlevel%
    
    rem // a string is a "relative pathname" iff it has no ':' as its second character, and an absolute pathname otherwise
    if not defined _inputType if "%input:~1,1%" == ":" (
        set _inputType=ABSOLUTE_PATHNAME
        echo You gave me absolute pathname.
    ) else (
        set _inputType=RELATIVE_PATHNAME
    )
    
    ENDLOCAL & set _inputType=%_inputType%
    
    上述脚本将导致以下结果:

    0
    You gave me absolute pathname.
    C:\Users\MikeW is of type ABSOLUTE_PATHNAME
    1
    documentation is of type FOLDER
    0
    Documents\Folder\inside is of type RELATIVE_PATHNAME
    
    PS:如果您可以删除
    echo%errorlevel%
    ,则可以简化
    :classifyInput
    功能,如下所示:

    findstr "[\\/:]"
    
    :classifyInput
    SETLOCAL
    set _inputType=
    set input=%~1
    
    rem // a string is a "name of folder" iff it has no '/', '\\' or ':' in it, and a pathname otherwise
    echo %input%|findstr /r "\\\\ / :" >nul
    if %errorlevel% == 1 (
        set _inputType=FOLDER
    ) else (
         if "%input:~1,1%" == ":" (
            set _inputType=ABSOLUTE_PATHNAME
            echo You gave me absolute pathname.
        ) else (
            set _inputType=RELATIVE_PATHNAME
        )
    )
    
    ENDLOCAL & set _inputType=%_inputType%
    

    命令SETIF可用于检查分配给环境变量的字符串是否包含特定字符或字符串

    例如:

    @echo off
    setlocal EnableExtensions
    for %%I in ("C:\Users\MikeW" "Folder\FileName" "Folder or file name") do call :ColonBackslash %%I
    endlocal
    goto :EOF
    
    :ColonBackslash
    set "Argument=%~1"
    
    rem Substitute in argument string all colons by nothing and compare this
    rem string with unmodified argument string. The argument string contains
    rem a colon if the modified and the unmodified strings are not equal.
    
    if not "%Argument::=%" == "%Argument%" (
        echo Colon in argument:        %Argument%
        goto :EOF
    )
    
    rem Substitute in argument string all backslashes by nothing and compare
    rem this string with unmodified argument string. The argument string
    rem contains a backslash if the modified and the unmodified strings
    rem are not equal.
    
    if not "%Argument:\=%" == "%Argument%" (
        echo Backslash in argument:    %Argument%
        goto :EOF
    )
    echo No colon or backslash in: %Argument%
    goto :EOF
    
    此批处理文件输出:

    Colon in argument:        C:\Users\MikeW
    Backslash in argument:    Folder\FileName
    No colon or backslash in: Folder or file name
    
    将字符串与替换字符/字符串与未修改字符串进行比较可用于确定输入字符串的类型,如下面的批处理代码所示:

    @echo off
    setlocal EnableExtensions
    for %%I in ("C:\Users\MikeW" "C:\Users\Mi:keW" "documentation" "\\server\share\folder" "\\server\share\folder1\..\folder2" "\\server\share\fo:lder" "\\server\" "\\server\share\folder\..\" "%SystemRoot%\..\" ".\Folder" "..\..\Folder" "\Windows" ">:Invalid") do call :classifyInput %%I
    endlocal
    goto :EOF
    
    :classifyInput
    rem Subroutine called with no parameter or with just "" as parameter.
    if "%~1" == "" goto :EOF
    set "Argument=%~1"
    rem Replace all forward slashes by backslashes in argument string.
    set "Argument=%Argument:/=\%"
    
    rem Is the second character a colon and third character a backlash?
    if "%Argument:~1,2%" == ":\" goto AbsolutePath
    
    rem Is there a colon anywhere else than at second position in argument?
    rem C:Folder is interpreted as invalid argument and not as relative
    rem path to subfolder "Folder" of current directory on drive C:.
    if not "%Argument::=%" == "%Argument%" (
        echo Invalid argument:  %1
        goto :EOF
    )
    
    rem Starts the argument with two backslashes?
    if "%Argument:~0,2%" == "\\" goto PathUNC
    
    rem Starts the argument with \ for a path relative to current drive?
    if "%Argument:~0,1%" == "\" (
        echo Relative path:     %1
        goto :EOF
    )
    
    rem Starts the argument with .\ for a path relative to current directory?
    if "%Argument:~0,2%" == ".\" (
        echo Relative path:     %1
        goto :EOF
    )
    
    rem Starts the argument with ..\ for a path relative to parent directory?
    if "%Argument:~0,3%" == "..\" (
        echo Relative path:     %1
        goto :EOF
    )
    
    rem Contains the argument a backslash for a path relative to current directory?
    if not "%Argument:\=%" == "%Argument%" (
        echo Relative path:     %1
        goto :EOF
    )
    
    echo Name without path: %1
    goto :EOF
    
    :AbsolutePath
    set "Remaining=%Argument:~2%"
    rem Is there a colon anywhere else after second position in argument?
    if not "%Remaining::=%" == "%Remaining%" (
        echo Invalid argument:  %1
        goto :EOF
    )
    
    rem Is the first character a drive letter if second character is a colon?
    set "FirstIsLetter="
    for /F "delims=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" %%# in ("%Argument:~0,1%") do set "FirstIsLetter=%%#"
    if not "%FirstIsLetter%" == "" (
        echo Invalid argument:  %1
        goto :EOF
    )
    
    rem Contains the absolute path also .\ or ..\ in path?
    if "%Argument:.\=%" == "%Argument%" (
        echo Absolute path:     %1
    ) else (
        echo Abs. + rel. path:  %1
    )
    goto :EOF
    
    :PathUNC
    rem Does the UNC path contain also a colon?
    if not "%Argument::=%" == "%Argument%" (
        echo Invalid argument:  %1
        goto :EOF
    )
    
    set "ServerName="
    set "ShareName="
    set "Remaining="
    for /F "tokens=1,2* delims=\" %%A in ("%Argument%") do (
        set "ServerName=%%A"
        set "ShareName=%%B
        set "Remaining=%%C"
    )
    
    rem Is there no share name specified after server name in UNC path?
    if "%ShareName%" == "" (
        echo Invalid argument:  %1
        goto :EOF
    )
    
    rem Is there an invalid share name specified after server name in UNC path?
    if "%ShareName%" == "." (
        echo Invalid argument:  %1
        goto :EOF
    )
    
    rem Is there an invalid share name specified after server name in UNC path?
    if "%ShareName%" == ".." (
        echo Invalid argument:  %1
        goto :EOF
    )
    
    rem Contains the UNC path also .\ or ..\ in remaining path?
    if "%Remaining:.\=%" == "%Remaining%" (
        echo UNC path:          %1
    ) else (
        echo UNC  + rel. path:  %1
    )
    goto :EOF
    
    输出为:

    Absolute path:     "C:\Users\MikeW"
    Invalid argument:  "C:\Users\Mi:keW"
    Name without path: "documentation"
    UNC path:          "\\server\share\folder"
    UNC  + rel. path:  "\\server\share\folder1\..\folder2"
    Invalid argument:  "\\server\share\fo:lder"
    Invalid argument:  "\\server\"
    UNC  + rel. path:  "\\server\share\folder\..\"
    Abs. + rel. path:  "C:\WINDOWS\..\"
    Relative path:     ".\Folder"
    Relative path:     "..\..\Folder"
    Relative path:     "\Windows"
    Invalid argument:  ">:Invalid"
    
    但是,对于检查参数字符串中的无效路径、文件夹或文件名,此批处理代码不完整。此批处理代码仍有许多可能未检测到的错误

    要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读为每个命令显示的所有帮助页面

    • 呼叫/?
    • echo/?
    • endlocal/?
    • 获取/?
    • goto/?
    • 如果/?
    • rem/?
    • 设置/?
    • setlocal/?
    如果参数字符串不包含或包含任何类型的路径且完全有效,则最好让Windows内核检查参数是否指定独立于现有文件夹或文件。请参阅以下主题:

    如果要对不存在的文件夹/文件进行有效性测试,只需创建该文件/文件夹,使用
    2>nul
    (请参阅Microsoft文章)抑制错误消息,并使用
    检查错误级别1是否为
    ,或使用
    如果存在“%~1”
    检查文件夹/文件是否可以成功创建,或者,如果此操作因无效的文件夹/文件名字符串、拒绝访问、缺少权限等而失败。

    前言:这不回答如何搜索字符串以查找
    /
    \
    ;它集中于路径的正确分类


    首先,我强烈建议避免使用纯字符串操作函数进行路径分类,因为这很容易出错;改用路径相关功能

    然后,您需要澄清在以下情况下例程应该输出什么:

    • 输入类似于
      名称
      :您将其称为
      文件夹
      ,但这也可能指向文件而不是文件夹,或者它甚至不存在,因此我们不知道它是文件还是文件夹;我对这些项目进行分类
      PURENAME
      ;请注意,这只是一个特定的相对路径
    • 输入类似于
      \name
      :这是我分类的
      相对的
      ,类似于您(
      相对路径名
    • 输入类似于
      D:\name
      :这是我分类的
      ABSOLUTE
      ,与您类似(
      ABSOLUTE\u路径名