从批处理脚本运行grep.exe(为Windows编译的Unix版本)时出错的原因是什么?

时间:2016-05-27 22:12:29

标签: windows batch-file grep

我尝试从批处理脚本运行grep.exe(针对Windows编译的Unix版本)并出现此错误:

      0 [main] grep 7760 C:\grep.exe: *** fatal error - add_item ("\??", "/", ...) failed, errno 22
Stack trace:
Frame        Function    Args
000FFFFABB6  0018007215E (00180267E4A, 00180218E59, 00600010000, 000FFFF8B30)
000FFFFABB6  00180046E52 (000FFFF9B98, 000FFFFABB6, 00000000000, 00000000000)
000FFFFABB6  00180046E92 (000FFFF9BB0, 00000000016, 00600010000, 000003F3F5C)
000FFFFABB6  001800DEEFD (000FFFFCBB0, 000FFFFCE00, 001800CF158, 00000000000)
000FFFFCC00  00180128545 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFCCC0  001800474B5 (00000000000, 00000000000, 00000000000, 00000000000)
00000000000  001800460AC (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0  00180046144 (00000000000, 00000000000, 00000000000, 00000000000)
End of stack trace

在批处理脚本中运行以下行后会显示以上错误消息:

for /f "usebackq delims=" %%a in (`reg query "hklm\system\currentcontrolset\control\session manager\environment" /v Path ^| %~dp0grep -i directory_being_searched_for `) do set pathExists=true

这行代码最初可能看起来很复杂,但最后的grep命令最终会被执行,但在某些时候失败了。

什么似乎导致了这种失败?

如果没有简单的解决方案,我不介意解决方法。

1 个答案:

答案 0 :(得分:1)

如果%~dp0grep(=批处理文件路径)的路径包含命令解释器输出的此列表grep.exe中的空格或其他语法关键字符,则应将

&()[]{}^=;!'+,`~括在双引号中本身在最后一页的命令提示符窗口cmd /?中运行。

还应附加文件扩展名.exe,以避免需要在批处理文件目录中搜索Windows命令解释程序。

但导致致命错误的主要问题很可能是由

替换的字符串
directory_being_searched_for
  1. 字符串是否用双引号括起来?
  2. 是否包含?*.等正则表达式字符?
  3. 是带路径的目录,因此还包含一个或多个反斜杠?
  4. grep 从Unix移植到Windows。因此, grep 将反斜杠解释为转义字符,如C / C ++ / C#/ JavaScript和许多其他编程和脚本语言,而不是像Windows这样的目录分隔符。

    我没有安装 grep (哪个版本从哪里下载?)因此无法重现此问题并找出导致致命错误的原因。

    但也许解决方案是使用 grep 选项-F grep 将搜索字符串模式解释为固定字符串而不是正则表达式。

    for /F "usebackq delims=" %%a in (`%SystemRoot%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v Path ^| "%~dp0grep.exe" -i -F "directory_being_searched_for"`) do set "pathExists=true"
    

    但是有更简单的解决方案,因为Windows为简单的固定字符串搜索和简单的正则表达式搜索提供了控制台应用程序查找 findstr

    查找

    的示例
    for /F "usebackq delims=" %%a in (`%SystemRoot%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v Path ^| "%SystemRoot%\System32\find.exe" "directory_being_searched_for"`) do echo set "pathExists=true"
    

    运营商| reg 的输出重定向到处理 STDOUT find的输入句柄 STDIN |必须使用^进行转义,以避免被解释为 命令,这会因语法错误导致批处理退出。有关详细信息,请参阅Microsoft有关Using command redirection operators的文章。

    但是这个简单的命令行不会验证完整的目录路径是否真的包含在Windows注册表中定义的环境变量 PATH 中。更好的验证将是例如:

    @echo off
    setlocal EnableDelayedExpansion
    set "PathExists=false"
    for /F "tokens=1,2*" %%A in ('%SystemRoot%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v Path') do (
        if /I "%%A"=="Path" (
            set "SystemPath=;%%C;"
            set "SystemPath=!SystemPath:"=!"
            if not "!SystemPath:;directory_being_searched_for;=!" == "!SystemPath!" set "PathExists=true"
        )
    )
    echo Path exists: %PathExists%
    endlocal
    

    要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。

    • echo /?
    • endlocal /?
    • find /?
    • for /?
    • if /?
    • reg /?
    • reg query /?
    • set /?
    • setlocal /?