1

我正在尝试了解发送给我的批处理文件,以便在他们解决问题时解决第三方程序中的错误。基本上,他们正在运行 findstr 正则表达式命令以确定字符串是否匹配。如果是这样,则在将其传递给原始命令行程序之前,将手动重新添加不应删除的特殊字符。

尽我所知,所提供的内容不起作用或我不明白。我在下面粘贴相关的代码部分。

@echo off
setlocal
set username=%1
shift
echo %username% | findstr /r "^\"[0-9][0-9]*\"" >nul
if not errorlevel 1 (set username=";%username:~0,9%=%username:~10,4%?")
echo %username%

我真正有疑问的三件作品如下:

  1. 我相信上述正则表达式的未转义解释是^"[0-9][0-9]*"我认为这意味着字符串必须以数字字符开头,然后必须包含零个或多个额外的纯数字字符才能找到匹配项。好吧,FINDSTR 似乎对转义的引号做了一些奇怪的事情,我无法让它与我尝试过的任何东西相匹配。如果我删除\"周围,[0-9][0-9]*那么我可以让它工作,但它不能正确拒绝非数字字符,例如输入字符串123456789O1234(该示例字符串中有一个字母 O 而不是零)。
  2. 有什么意义>nul
  3. 检查等于 0 的错误级别而不是“非错误级别 1”不是更好吗,因为它可能返回错误级别 2

无论如何,以下代码有效,但并不像我想要的那样精确。我只是想了解为什么正则表达式字符串中的引号不起作用。也许这是 FINDSTR 的一个限制,但我还没有遇到任何确定的东西。

@echo off
setlocal
set username=%1
shift
echo %username% | findstr /r "^[0-9][0-9]*" >nul
if not errorlevel 1 (set username=";%username:~0,9%=%username:~10,4%?")
echo %username%

我可以通过重复类 14 次来解决这个问题,因为这是我的情况下的字符数(超过 15 个类会导致它崩溃- 滚动到底部)。我仍然对如何更简单地实现这一点感到好奇,当然还有剩下的 2 个问题。

编辑/工作解决方案

@echo off
setlocal enableDelayedExpansion
set username=%~1
shift
echo !username!|findstr /r /c:"^[0-9][0-9]*$" >nul 
if not errorlevel 1 (set username=";!username:~0,9!=!username:~10,4!?")
echo !username!

笔记:

  • 当我将现有代码修改为更接近 dbenham 的代码后第一次运行它时,enableDelayedExpansion和设置用户名的引号一样给出了错误(见下文)。我无法复制我做错的事情,但现在一切正常(以防其他人遇到同样的问题)。
  • 我曾尝试使用$EOL 标记(这是强制它仅匹配数字内容的关键),但我认为其他问题阻碍了我认为这不是解决方案。此外,为了确保$作品不会错过这部分 dbenham 的回答“......您还必须确保您的回显值和管道符号之间没有空格。”
  • 简而言之,似乎试图在 findstr 的正则表达式中添加双引号是错误的语法/不起作用/等等...除非您实际上正在寻找匹配 " 在您正在解析的字符串/文件中。请参阅 dbenham 的答案为了清楚起见,正如他所指出的,您可以使用 %~1 从参数中去除引号,而不是将其添加到您的正则表达式中(并在需要时以编程方式将它们重新添加)。

错误信息

C:>sample.bat 123456789
'enableDelayedExpansion' is not recognized as an internal or external command,
operable program or batch file.
'"' is not recognized as an internal or external command,
operable program or batch file.
!username!

参考链接:

4

1 回答 1

4

以相反的顺序回答您的问题:

3)if not errorlevel 1可能与if %errorlevel%==0IF ERRORLEVEL 1 表示如果 ERRORLEVEL 大于或等于 1 相同。所以在前面放置 NOT 表示如果 ERRORLEVEL 小于 1。我相信 FINDSTR 永远不会返回负的 ERRORLEVEL,所以语法应该是好的。

2)>nul将 FINDSTR 的 stdout 输出重定向到 nul 设备,这意味着它禁用了输出。通常会打印任何匹配的行。你只对返回码感兴趣——你不想看到输出。

1) 原始正则表达式将匹配任何以引号开头的输入字符串,后跟至少一个数字,然后是另一个引号。它忽略第二个引号之后可能出现的任何字符。

因此以下字符串(包括引号)将匹配:

  • “0”
  • “01234”
  • “0”一
  • “01234”一

以下字符串将不匹配:

  • 0
  • 01234
  • “”
  • “0a”

如果匹配字符串中的位数达到一定长度,则原始代码会出现问题,因为结束引号被剥离导致结束 ) 被引用,因此脚本的其余部分失败。

我不了解您的要求,所以我不知道如何修复代码。

听起来您不想匹配具有非数字的字符串。这意味着您需要在正则表达式的末尾包含行尾标记 $。但您还必须确保回显值和管道符号之间没有空格。

我相信您可能不希望在您的价值中使用引号,(否则您应该在最后以编程方式添加它们)。您可以使用 %~1 从提供的参数中删除任何封闭引号。

如果您要检查参数 1 是否仅由数字组成,则可以使用:

setlocal enableDelayedExpansion
set "username=%~1"
echo !username!|findstr /r "^[0-9][0-9]*$" >nul

我使用了延迟扩展,因为您无法控制 %1 中的字符,以及它是否包含特殊字符,如 & 或 | 如果您使用正常扩展,它将导致问题。我给出的语法不是防弹的,但它可以处理大多数“正常”情况。

在您的情况下没有必要,但我更喜欢使用 /c 选项,以防您的搜索字符串包含空格。所以上面可以写成

echo !username!|findstr /r /c:"^[0-9][0-9]*$" >nul

我觉得奇怪的是,如果原始代码和修改后的代码与您的正则表达式不匹配,它只会通过用户名。也许这是你的意图,也许不是。

于 2012-05-17T03:56:54.007 回答