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

Jat*_*mar 4 windows escaping pipe batch-file call

我正在编写一个函数来执行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
Run Code Online (Sandbox Code Playgroud)

我成功地传递了简单的命令并获得输出.但对于像这样的电话

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

我知道我们需要逃避|^在,但如果我尝试通过^|在函数参数字符串,它改变它^^|再次抛出错误.

我错过了什么吗?

jeb*_*jeb 11

这是CALL命令的效果.

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

看到这个

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

call echo "^^^^"
call call echo "^^^^"
call call call echo "^^^^"
Run Code Online (Sandbox Code Playgroud)

产量

^^
^^
^^
"^^^^^^^^"
"^^^^^^^^^^^^^^^^"
"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
Run Code Online (Sandbox Code Playgroud)

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

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

:runShellCmd
   setlocal EnableDelayedExpansion
   set "param=%~1"
   set param
   set "param=!param:^^=^!"
   for .... ('!param!')
Run Code Online (Sandbox Code Playgroud)

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

set "caret=^"
CALL :runShellCmd "echo Jatin Kumar %%caret%%| find /c /i "
Run Code Online (Sandbox Code Playgroud)

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


MC *_* ND 5

@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]
Run Code Online (Sandbox Code Playgroud)

我想我缺少了一些东西,因为这对我有用。

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

@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]
Run Code Online (Sandbox Code Playgroud)