batch file - Pipe in for loop breaks double quoted variables -


situation: using batchscript retrieve values json.
i've got following batchscript:

@echo off  echo enter npo.nl program-url : set url= set /p url= :: http://www.npo.nl/buitenhof/03-05-2015/vpwon_1232766/poms_vpro_850040 example setlocal enabledelayedexpansion /f "tokens=6 delims=/" %%a in ("%url%") (     /f "delims=" %%b in ('curl.exe -s http://e.omroep.nl/metadata/aflevering/%%a ^| jq.exe -r -r -s ".[1+index(\"^(\"): rindex(\"^)\")]"') (         /f "delims=" %%c in ('echo %%b ^| jq.exe -r .start') set ss=%%c         /f "delims=" %%c in ('echo %%b ^| jq.exe -r .eind') set to=%%c         /f "delims=" %%c in ('echo %%b ^| jq.exe -r .tijdsduur') set t=%%c         echo start:    !ss!         echo end:      !to!         echo duration: !t!     ) ) endlocal pause 

what do?
upon having entered npo.nl program-url, first for-loop strips url down prid:poms_vpro_850040. in second for-loop curl.exe retrieves json...:

parsemetadata({"status":"ok","version":"1.11.12","prid":"vpwon_1232766","titel":"schuim & as","aflevering_titel":"","info":"schuim & met jelle brandt corstius","ratio":"16:9","medium":"tv","gidsdatum":"2015-05-03","tijdsduur":"00:05:27","start":"00:23:13","eind":"00:28:40","url":"","webcast":1,"images":[{"size":"640x480","ratio":"4:3","url":"http:\/\/images.poms.omroep.nl\/image\/sx480\/c640x480\/606030.jpg"},{"size":"720x405","ratio":"16:9","url":"http:\/\/images.poms.omroep.nl\/image\/sx405\/c720x405\/606030.jpg"}],"omroepen":[{"naam":"vpro"}],"pubopties":["adaptive","h264_bb","h264_sb","h264_std"],"tt888":"ja","serie":{"srid":"vpwon_1232748","serie_titel":"buitenhof","serie_url":null},"sitestat":{"baseurl":"http:\/\/b.scorecardresearch.com\/p?c1=2&c2=17827132&ns_site=po-totaal","programurl":"uitzendinggemist.publiekeomroep.ondemand.tv.buitenhof.20150503","programurlpost":"category=uitzendinggemist&thema=informatief&po_source=video","baseurl_subtitle":"http:\/\/nl.sitestat.com\/klo\/po\/s","subtitleurl":"uitzendinggemist.publiekeomroep.ondemand.tv.player.tt888.buitenhof","subtitleurlpost":"category=uitzendinggemist&po_source=video&po_sitetype=webonly"},"reclame":"http:\/\/pubads.g.doubleclick.net\/gampad\/ads?_cookie_&impl=s&gdfp_req=1&env=vp&output=xml_vast2&unviewed_position_start=1&sz=_sz_&correlator=_correlator_&iu=\/9233\/_site_\/buitenhof&url=_url_&cust_params=genre%3dinformatief%2cnieuws%2factualiteiten%26dur%3d3284%26prid%3dvpwon_1232766%26srid%3dvpwon_1232748%26player%3d_player_","streamsense":{"episode":"buitenhof","program":"buitenhof","station":"nederland_1","sitestatname":"uitzendinggemist.publiekeomroep.ondemand.tv.buitenhof.20150503","sko":"true","sko_dt":"20150503","sko_pr":"buitenhof","sko_stid":"1","sko_ty":"tv.seg","sko_prid":"vpwon1232766","sko_t":"1210","sko_cl":"3284"}}) //epc 

...and sends through pipe jq.exe removes non-json-data parsemetadata( , ) //epc , leaves single line intact. 2 reasons: 1) non-json-data present can't process anything, , 2) for-loops process 1 line @ time.
subsequent jq.exe's retrieve values specified objects without double quotes.
long curl.exe , jq.exe in same directory batchscript, or in %path%-variable, working fine:

start:     00:23:13 end:       00:28:40 duration:  00:05:27 

now want call curl.exe , jq.exe map. 1 spaces in it:

set curl="c:\map spaces\curl.exe" set jq="c:\map spaces\jq.exe"  @echo off  echo enter npo.nl program-url : set url= set /p url= :: http://www.npo.nl/buitenhof/03-05-2015/vpwon_1232766/poms_vpro_850040 example setlocal enabledelayedexpansion /f "tokens=6 delims=/" %%a in ("%url%") (     /f "delims=" %%b in ('%curl% -s http://e.omroep.nl/metadata/aflevering/%%a ^| %jq% -r -r -s ".[1+index(\"^(\"): rindex(\"^)\")]"') (         /f "delims=" %%c in ('echo %%b ^| %jq% -r .start') set ss=%%c         /f "delims=" %%c in ('echo %%b ^| %jq% -r .eind') set to=%%c         /f "delims=" %%c in ('echo %%b ^| %jq% -r .tijdsduur') set t=%%c         echo start:    !ss!         echo end:      !to!         echo duration: !t!     ) ) endlocal pause 

for 2nd for-loop causes problems:

'c:\map' not recognized internal or external command, operable program or batch file. 

while 'echo %%x ^| %jq%' work, seems '%curl% ^| %jq%' doesn't. reason things go wrong 2 variables in pipe parsed.

well, no more pipe then:

set curl="c:\map spaces\curl.exe" set jq="c:\map spaces\jq.exe"  @echo off  echo enter npo.nl program-url : set url= set /p url= :: http://www.npo.nl/buitenhof/03-05-2015/vpwon_1232766/poms_vpro_850040 example setlocal enabledelayedexpansion /f "tokens=6 delims=/" %%a in ("%url%") (     /f "delims=" %%b in ('%curl% -s http://e.omroep.nl/metadata/aflevering/%%a') (         /f "delims=" %%c in ('echo %%b ^| %jq% -r -r -s ".[1+index(\"^(\"): rindex(\"^)\")]"') (             /f "delims=" %%d in ('echo %%c ^| %jq% -r .start') set ss=%%d             /f "delims=" %%d in ('echo %%c ^| %jq% -r .eind') set to=%%d             /f "delims=" %%d in ('echo %%c ^| %jq% -r .tijdsduur') set t=%%d             echo start:    !ss!             echo end:      !to!             echo duration: !t!         )     ) ) endlocal pause 

now curl.exe , jq.exe each in for-loop. @ first seems work fine. 3 values echoed, things go wrong:

parse error: invalid numeric literal @ line 1, column 5  parse error: invalid numeric literal @ line 1, column 5 parse error: invalid numeric literal @ line 1, column 5 parse error: invalid numeric literal @ line 1, column 5 start:    00:23:13 end:      00:28:40 duration: 00:05:27 

like said before; for-loops parse , process 1 line @ time. non-json-data //epc on 2nd line causes for-loop start over, goes horribly wrong can see. that's reason pipe between curl , jq in code above. output 1 single line process. sadly didn't work either...sigh.

of course using temporary files last resort when curl , jq still in map spaces in it, prefer use variables, i'm trying solve pipe-issue. i've tried 'usebackq' in for-loop using backticks around command instead of single-quotes instance, no avail.
far haven't found solution. have explanation behaviour , how solve it?

thanks dave benham's answer on related issue i've found solution!
appeared specific /f bug in winxp, , guess what, here i'm still on winxp. fix main offender, curl-pipe-jq-for-loop, had put ^" in front of and after entire command. entire batchscript, i've further improved:

@echo off cls  :: npo json-extractor geschreven door reino wijnsma, 2015 (reino@degeelebosch.nl)  set batchname=npo json-extractor set version=1.1 title %batchname% %version%  set curl="c:\map spaces\curl.exe" set jq="c:\map spaces\jq-1.5rc1.exe"  :check if exist %curl% (     if exist %jq% (         goto input     ) else (         echo 'jq.exe' niet gevonden.         echo.         pause         goto :eof     )     goto input ) else (     echo 'curl.exe' niet gevonden.     echo.     pause     goto :eof )  :input echo voer npo.nl programmalink in : set url= set /p url= :: http://www.npo.nl/buitenhof/03-05-2015/vpwon_1232766/poms_vpro_850040 bijvoorbeeld if "%url%"=="" goto :eof  setlocal enabledelayedexpansion %%a in ("%url%") (     /f "delims=" %%b in ('^"%curl% -s http://e.omroep.nl/metadata/aflevering/%%~nxa ^| %jq% -r -r -s ".[1+index(\"(\"): rindex(\"^)\")]"^"') (         echo.         echo json:         /f "delims=" %%c in ('echo %%b ^| %jq% .') echo %%c         echo.         /f "tokens=1-3" %%c in ('echo %%b ^| %jq% -r "[.tijdsduur,.start,.eind] | @tsv"') (             echo tijdsduur: %%c             if not "%%d"=="" (                 set ss=%%d                 set to=%%e                 set /a "_ss=((1!ss:~0,2!-100)*3600)+((1!ss:~3,2!-100)*60)+(1!ss:~6,2!-100)"                 set /a "_to=((1!to:~0,2!-100)*3600)+((1!to:~3,2!-100)*60)+(1!to:~6,2!-100)"                 echo start:     %%d (!_ss!s^)                 echo einde:     %%e (!_to!s^)             )         )     ) ) echo. endlocal goto input 


important notes future reference:

jq-syntax:           jq -r -r -s  '.[1+index("("):   rindex(")")]' cmd-shell:           jq -r -r -s  ".[1+index(\"(\"): rindex(\")\")]" for-loop:           'jq -r -r -s  ".[1+index(\"(\"): rindex(\"^)\")]"' for-loop (path): '^"%jq% -r -r -s ".[1+index(\"(\"): rindex(\"^)\")]"^"' 

- cmd-shell have escape double quotes line-feed \.
- while 2 of closing parenthesis part of jq's syntax, 1 between double quotes not. when in for-loop, prevent for-loop closing, you'd have escape 1 ^.
- when jq's executable path put in variable double quotes, circumvent winxp bug, you'd have put entire command between ^", because parenthesis considered special characters! workaround compatible vista , beyond. (see dostips.com)


Comments