我正在编写一个函数来执行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
。
我知道我们需要使用|
来转义^
但是如果我尝试在函数参数字符串中传递^|
,它会再次将其更改为^^|
抛出错误。
我错过了什么吗?
答案 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]