设置delayedexpansion时如何检查变量的特殊字符

时间:2017-08-04 10:44:07

标签: windows batch-file

我想知道字符串是否具有任何特殊字符。 我尝试了以下使用环境变量,这里检测@字符正常工作

@echo off
set x=Stack@123Overflow
echo %x%
echo %x% | findstr /r "^[^\\/?%%*:|<>\_\.-~!@#$&()+="]*$^" > nul
echo %errorlevel%
pause

输出为1
output 1

但是,当我启用延迟扩展时,我的errorlevel0,实际应为1

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set x=Stack@123Overflow
echo !x!
echo !x! | findstr /r "^[^\\/?%%*:|<>\_\.-~!@#$&()+="]*$^" > nul
echo %errorlevel%
pause

这是第二个代码的输出(输出为0):
output 0

我想通过仅启用delayedexpansion来实现此目的,并且我希望将其与wmic(wmic logicaldisk get VolumeName)命令一起使用

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

SET count=0
FOR /F "tokens=1 delims= " %%F IN ('wmic logicaldisk get VolumeName') DO (
    for /f "tokens=1 delims= " %%B in ("%%F") do (
        set x=%%B
        echo !x!
        echo !x! | findstr /r "^[^\\/?%%*:|<>\_\.-~!@#$&()+="]*$^" > nul
        echo %errorlevel%
    )
)
pause

我也尝试使用!errorlevel!代替%errorlevel%,但这不起作用。

1 个答案:

答案 0 :(得分:3)

在准备要在管道内执行的命令时,解析器处理转义字符的问题。传递给findstr的正则表达式变为

[\\/?%*:|<>\_\.-~@#$&()+=]*$

尝试

echo !x! | findstr /r "^^[^^\\/?%%*:|<>\_\.-~^!@#$&()+=""]*$"

并且,正如jeb所指出的,在你的上一个代码中,你必须将echo %errorlevel%(变量在解析for命令时展开)更改为echo !errorlevel!(变量在执行之前被扩展) echo命令)

已修改以适应评论

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "test_data=clean"                    & call :runTest
    set "test_data=with spaces"              & call :runTest
    set "test_data=with ending spaces "      & call :runTest
    set "test_data= with starting spaces"    & call :runTest
    set "test_data=with!exclamation"         & call :runTest
    set "test_data=with%%percentsign"        & call :runTest
    set "test_data=with^caret"               & call :runTest
    set "test_data=with:colon"               & call :runTest
    set "test_data=with""quotes"             & call :runTest
    set "test_data=with&ampersand"           & call :runTest
    set "test_data=with*?wildcards"          & call :runTest
    set "test_data=.\-/?%%*:|<>_~^!@#$&()+=" & call :runTest

    goto :eof

:runTest
    setlocal enabledelayedexpansion
        set test_data
        echo [!test_data!]
        (cmd /v/c"(@echo !test_data!)")| >nul findstr /x /r /c:"[^^ .\-\\/?%%*:|<>_~^!@#$&()+=""^^]*"
        echo errorlevel = !errorlevel!
    endlocal
    echo ----------------------------------------------------------------------

输出:

S:\>q45504784.cmd
test_data=clean
[clean]
errorlevel = 0
----------------------------------------------------------------------
test_data=with spaces
[with spaces]
errorlevel = 1
----------------------------------------------------------------------
test_data=with ending spaces
[with ending spaces ]
errorlevel = 1
----------------------------------------------------------------------
test_data= with starting spaces
[ with starting spaces]
errorlevel = 1
----------------------------------------------------------------------
test_data=with!exclamation
[with!exclamation]
errorlevel = 1
----------------------------------------------------------------------
test_data=with%percentsign
[with%percentsign]
errorlevel = 1
----------------------------------------------------------------------
test_data=with^caret
[with^caret]
errorlevel = 1
----------------------------------------------------------------------
test_data=with:colon
[with:colon]
errorlevel = 1
----------------------------------------------------------------------
test_data=with""quotes
[with""quotes]
errorlevel = 1
----------------------------------------------------------------------
test_data=with&ampersand
[with&ampersand]
errorlevel = 1
----------------------------------------------------------------------
test_data=with*?wildcards
[with*?wildcards]
errorlevel = 1
----------------------------------------------------------------------
test_data=.\-/?%*:|<>_~^!@#$&()+=
[.\-/?%*:|<>_~^!@#$&()+=]
errorlevel = 1
----------------------------------------------------------------------

S:\>