在函数调用Windows批处理脚本中转义PIPE字符

时间:2014-03-04 08:12:15

标签: windows batch-file escaping call pipe

我正在编写一个函数来执行shell命令并在批处理脚本中捕获它的输出。

:runShellCmd
   setlocal EnableDelayedExpansion
   SET lf=-
   FOR /F "delims=" %%i IN ('%~1') DO if "%out%" == "" (set out=%%i) else (set out=!out!%lf%%%i)
   echo "Cmd output: %out%"
   SET "funOut=%out%"
ENDLOCAL & IF "%~1" NEQ "" SET %~2=%out%
goto :EOF

我成功传递了简单的命令并获得了输出。但对于像

这样的电话

CALL :runShellCmd "echo Jatin Kumar | find /c /i "jatin""失败,错误为unexpected | character

我知道我们需要使用|来转义^但是如果我尝试在函数参数字符串中传递^|,它会再次将其更改为^^|抛出错误。

我错过了什么吗?

2 个答案:

答案 0 :(得分:9)

这是CALL命令的效果。

CALL命令将其中一个批处理解析器阶段中的所有插入符号加倍 通常你不会看到这个,因为插入符号将在加倍后直接用作逃逸字符。

见这个

call echo ^^^^
call call echo ^^^^
call call call echo ^^^^

call echo "^^^^"
call call echo "^^^^"
call call call echo "^^^^"

输出

^^
^^
^^
"^^^^^^^^"
"^^^^^^^^^^^^^^^^"
"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"

但哇你能逃脱你的管道角色吗? 你不能!

但你可以在你的功能中添加一个插入卸妆器。

:runShellCmd
   setlocal EnableDelayedExpansion
   set "param=%~1"
   set param
   set "param=!param:^^=^!"
   for .... ('!param!')

或者你可以在调用函数时使用转义技巧。

set "caret=^"
CALL :runShellCmd "echo Jatin Kumar %%caret%%| find /c /i "

这是有效的,因为%%caret%%将在CALL caret doubling phase之后展开。

答案 1 :(得分:4)

@echo off
    setlocal enableextensions disabledelayedexpansion 

    call :test "echo(this|find "t""
    exit /b

:test
    set "x=%~1"
    for /f "delims=" %%f in ('%x:|=^|%') do echo [%%f]

我想我错过了什么,因为这适合我。

已编辑 - 这应该是一个更通用的解决方案。不是防弹而是骨架。

@echo off
    setlocal enableextensions disabledelayedexpansion 

    call :test "(echo(this&echo(that)|find "t" 2>nul|sort&echo end"
    exit /b

:test
    set "x=%~1"
    set "x=%x:|=^|%"
    set "x=%x:>=^>%"
    set "x=%x:<=^<%"
    set "x=%x:&=^&%"
    set "x=%x:)=^)%"
    for /f "delims=" %%f in ('%x%') do echo [%%f]