Batch file 用于格式为xxxx.xxxx.xxxx的MAC的批量正则表达式

Batch file 用于格式为xxxx.xxxx.xxxx的MAC的批量正则表达式,batch-file,cmd,Batch File,Cmd,我一直在尝试解析格式为“xxxx[Delimiter]xxxx[Delimiter]xxxx”的mac,其中“x”在[0-9,a-F,a-F]中,“Delimiter]”在[:,,-]中。我尝试了下面的代码,并引用了带有标题和标题的示例 我也试过这个 echo %MACAddr%|findstr /r "^([0-9A-Fa-f]{4})([:.-])([0-9A-Fa-f]{4})([:.-])([0-9A-Fa-f]{4})$" 但是只有当errorlevel 1(echo Mac%MAC

我一直在尝试解析格式为“xxxx[Delimiter]xxxx[Delimiter]xxxx”的mac,其中“x”在[0-9,a-F,a-F]中,“Delimiter]”在[:,,-]中。我尝试了下面的代码,并引用了带有标题和标题的示例

我也试过这个

echo %MACAddr%|findstr /r "^([0-9A-Fa-f]{4})([:.-])([0-9A-Fa-f]{4})([:.-])([0-9A-Fa-f]{4})$"

但是只有当errorlevel 1(echo Mac%MACAddr%与xxxx.xxxx.xxxx格式不同)时,它才会运行
。请告诉我我做错了什么。

findstr
的REGEX子集非常有限(请参见
了解/?

你的要求可以表述为:

findstr /ri "^[0-9A-F][0-9A-F][0-9A-F][0-9A-F].[0-9A-F][0-9A-F][0-9A-F][0-9A-F].[0-9A-F][0-9A-F][0-9A-F][0-9A-F]$"

其中
表示“任何字符”。如果你想把它分解成
-
作为分隔符,使用
[;.-]
而不是
。如果分隔符可能存在或不存在,请使用
[;.-]*
(其中
*
表示“零或多”-抱歉,没有
“无”或“一”与
findstr

你知道当你遇到这样的问题时,你必须一直坚持下去直到找到解决方案吗?

因此,第一部分只是生成一系列用于测试的“可能”条目。带有
macaddr
分配给测试字符串的例程
:testmacaddr
实际执行工作,标签
:report
后的部分报告结果-如果定义了
invalid
,则提供的
macaddr
%invalid%
中的原因无效

%%d循环的
检查初始或终端分隔符,并在
:tokenise
例程中为内部循环建立控制字符串

:tokenise
例程使用当前分隔符检查前四个令牌的提供地址,将八位字节分配给%%p..%s。因为我们想要的正好是3,所以
%%s
必须为空,
%%r
不为空才能使用
:validate进行进一步验证

:validate
检查每个八位字节是否与
/x
完全匹配
/i
/r
正则表达式1,2,3或4个十六进制数字不区分大小写。如果八位字节未通过所有这些测试,
invalid
被设置为失败的八位字节数。如果所有八位字节都通过,则
valid
设置为
Y

因此,如果没有失败的条件,并且
:validate
例程被传递了一次,那么该值是有效的。

如中所述,
findstr
没有完全的正则表达式支持

因此,不支持分组(
/
)、备选方案(
)、重复(
{
/
}
)和选项(

还有一个需要考虑的额外限制:字符类(
[
/
]
)的数量限制为15,因此指定16个或更多会导致错误。
还不够,字符类有缺陷,它们可能匹配意外字符;例如,范围
[0-9]
匹配十进制数字
0
9
,但也匹配字符
2
3
;范围
[A-Z]
(不带
/I
选项)也错误地匹配小写字母,如
Z
,还匹配一些其他字符,如
Á
á
,具体取决于当前代码页

有关
findstr
的所有缺陷和限制,请参阅《大词典》


要解决所有这些问题,您可以指定多个搜索字符串,如
findstr/R“search\u string1 search\u string2”
(空格分隔列表)或
findstr/R/C:“search string1”/C:“search string2”
(这甚至允许空格成为搜索字符串的一部分)

我会这样做你的任务:

echo%MACAddr%|(findstr/I/X/R)^
/C:“[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]”^
/C:“[0-9A-F][0-9A-F][0-9A-F]:[0-9A-F][0-9A-F][0-9A-F][0-9A-F]:[0-9A-F][0-9A-F][0-9A-F][0-9A-F]。”^
/C:“[0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F]”^
/C:“[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]\.[0-9A-F][0-9A-F]\.[0-9A-F][0-9A-F]\.[0-9A-F][0-9A-F]”^
/C:“[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:”^
/C:“[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F]-[0-9A-F]。”^
)
您也可以在不使用
/C
的情况下使用语法,但阅读起来很糟糕:

[0-9A-F][0-9A-F][0-9A-9A-F][0-9A-9A-F[0-9A-F[0-9A-F[0-9A-F[0-9A-F[0-9A-F[0-9A-F[0-9A-F[0-9A-9A-F][[0-9A-9A-F][[0-9A-9A-F][[0-9A-9A-F][0-9A-9A-9A-F][0-F[0-9A-9A-9A-F[0-9A-F[0-9A-F[0-9A-9A-F-F[0-F[0-9A-9A-F[0-F-F-9-F][[0-9A-9A-9A-F][[0-9-F-F[0-F[0-[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F](0-9A-F][0-9A-9A-F[0-9A-F[0-9A-F][0-9A-9A-F[0-9A-F[0-9A-F[0-9A-F[0-9A-F[0-9A-9A-F[0-9A-9A-F[0-9A-F[0-9A-F][0-9A-9A-F][0-9A-9A-F[0-F][0-9A-F[0-9A-F][0-9A-F[0-9A-F][0-9A-F][0-F[0-9A-F[0-9-F[0-9A-F[0-F[0-9-9-9-F[0-9A-F[0-9-F[0-F[0-9-9-9-9-9-9-9-[0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F]。”
您可以将搜索字符串放入文本文件(例如
MACAddrRegEx.txt
)并使用以下语法:

echo%MACAddr%| findstr/I/X/R/G:“MACAddrRegEx.txt”
MACAddrRegEx.txt
的内容是:

[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]
[0-9A-F][0-9A-F][0-9A-F][0-9A-F]:[0-9A-F][0-9A-F][0-9A-F]:[0-9A-F][0-9A-F][0-9A-F]
[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]
[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]\.[0-9A-F][0-9A-F]\.[0-9A-F][0-9A-F]\.[0-9A-F][0-9A-F]
[0-9A-F][0-9A-F]:[0-9A-F][0-9A
findstr /ri "^[0-9A-F][0-9A-F][0-9A-F][0-9A-F].[0-9A-F][0-9A-F][0-9A-F][0-9A-F].[0-9A-F][0-9A-F][0-9A-F][0-9A-F]$"
@ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION 

:: This simply tests various addresses

FOR %%D IN (":" "." "-" "#") DO FOR %%T IN (
.012a.23fa.5ffc
012a.23fa.5ffc.
012a.23fa.5ffc
012a.23fa
012a.23fa.5ffc.0123
01ka.23fa.5ffc
012a.23ga.5ffc
012a.23fa.5pfc
012a1.23fa.5ffc
012a.263fa.5ffc
012a.23fa.58ffc
1.2.3
03ed.2.f
) DO (
 set "MACAddr=%%T"
 SET "macaddr=!macaddr:.=%%~D!"
 CALL :testmacaddr
)
SET "macaddr="
CALL :testmacaddr

GOTO :eof

:testmacaddr
SET "invalid="
SET "valid="
If NOT DEFINED MACAddr SET "invalid=MACADDR not set"&GOTO report
FOR %%d IN (":" "." "-") DO (
 IF "%macaddr:~0,1%"=="%%~d" SET "invalid=Initial"
 IF "%macaddr:~-1%"=="%%~d" SET "invalid=Terminal"
 SET "control="tokens=1-4delims=%%~d""
 CALL :tokenise
)
:report
IF NOT DEFINED valid IF NOT DEFINED invalid SET "invalid=Incorrect octet count"
:: pad 'macaddr' with a goodly number of spaces,
:: show the first 20 character of the result and the 'invalid' value

SET "macaddr=%macaddr%                          "
ECHO %macaddr:~0,20% : %invalid%
GOTO :EOF

:tokenise
FOR /f %control% %%p IN ("%macaddr%") DO (
 IF "%%s"=="" IF "%%r" neq "" (
  SET /a octets=1
  CALL :validate %%p %%q %%r
 )
)

GOTO :eof

:validate
ECHO %1|FINDSTR /r /x /i "[0-9a-f]">NUL
IF NOT ERRORLEVEL 1 GOTO valok
ECHO %1|FINDSTR /r /x /i "[0-9a-f][0-9a-f]">NUL
IF NOT ERRORLEVEL 1 GOTO valok
ECHO %1|FINDSTR /r /x /i "[0-9a-f][0-9a-f][0-9a-f]">NUL
IF NOT ERRORLEVEL 1 GOTO valok
ECHO %1|FINDSTR /r /x /i "[0-9a-f][0-9a-f][0-9a-f][0-9a-f]">NUL
IF ERRORLEVEL 1 SET "invalid=Octet %octets%"&GOTO :eof
:valok
shift
SET /a octets+=1
IF %octets% lss 4 GOTO validate
SET "valid=Y"

GOTO :eof