문제

I am writing a function to execute shell commands and capture its output in a batch script.

: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

I have been successful in passing simple commands and getting output. But for calls like

CALL :runShellCmd "echo Jatin Kumar | find /c /i "jatin"" it fails with error unexpected | character.

I know we need to escape | with ^ in for but if I try to pass ^| in the function argument string, it changes it to ^^| which again throws error.

Am I missing something?

도움이 되었습니까?

해결책

This is an effect of the CALL command.

The CALL command doubles all carets in one of the batch parser phases.
Normally you wouldn't see this, as the carets will be used as an escape charater directly after the doubling.

See this

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

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

Output

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

But how do you can escape your pipe character?
You can't!

But you can add a caret remover in your function.

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

Or you could use an escaping trick when calling your function.

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

This works, as the %%caret%% will be expanded after the CALL caret doubling phase.

다른 팁

@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]

I think i'm missing something, because this works for me.

EDITED - This should be a more general solution. Not bulletproof but a skeleton.

@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]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top