【发布时间】:2015-07-19 04:58:10
【问题描述】:
情况:使用批处理脚本从 JSON 中检索某些值。
我有以下批处理脚本:
@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 for example
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=6 delims=/" %%A IN ("%url%") DO (
FOR /F "delims=" %%B IN ('curl.exe -s http://e.omroep.nl/metadata/aflevering/%%A ^| jq.exe -R -r -s ".[1+index(\"^(\"): rindex(\"^)\")]"') DO (
FOR /F "delims=" %%C IN ('ECHO %%B ^| jq.exe -r .start') DO SET ss=%%C
FOR /F "delims=" %%C IN ('ECHO %%B ^| jq.exe -r .eind') DO SET to=%%C
FOR /F "delims=" %%C IN ('ECHO %%B ^| jq.exe -r .tijdsduur') DO SET t=%%C
ECHO Start: !ss!
ECHO End: !to!
ECHO Duration: !t!
)
)
ENDLOCAL
PAUSE
它有什么作用?
输入 npo.nl 程序 URL 后,第一个 for 循环将 url 剥离到 prid:POMS_VPRO_850040。在第二个 for 循环 curl.exe 中检索 JSON...:
parseMetadata({"STATUS":"OK","VERSION":"1.11.12","prid":"VPWON_1232766","titel":"Schuim & As","aflevering_titel":"","info":"Schuim & As 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
...并通过管道将其发送到 jq.exe,该管道会删除非 JSON 数据 parseMetadata( 和 ) //epc 并保持单行完整。这有两个原因:1) 存在非 JSON 数据时,我们无法处理任何内容,以及 2) for 循环一次只能处理 1 行。
后面的 jq.exe 对指定对象的检索值不带双引号。
只要 curl.exe 和 jq.exe 与批处理脚本位于同一目录中,或者在 %path% 变量中,就可以正常工作:
Start: 00:23:13
End: 00:28:40
Duration: 00:05:27
现在我想从另一个地图调用 curl.exe 和 jq.exe。一个有空格的:
SET curl="C:\map with spaces\curl.exe"
SET jq="C:\map with 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 for example
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=6 delims=/" %%A IN ("%url%") DO (
FOR /F "delims=" %%B IN ('%curl% -s http://e.omroep.nl/metadata/aflevering/%%A ^| %jq% -R -r -s ".[1+index(\"^(\"): rindex(\"^)\")]"') DO (
FOR /F "delims=" %%C IN ('ECHO %%B ^| %jq% -r .start') DO SET ss=%%C
FOR /F "delims=" %%C IN ('ECHO %%B ^| %jq% -r .eind') DO SET to=%%C
FOR /F "delims=" %%C IN ('ECHO %%B ^| %jq% -r .tijdsduur') DO SET t=%%C
ECHO Start: !ss!
ECHO End: !to!
ECHO Duration: !t!
)
)
ENDLOCAL
PAUSE
对于第二个 for 循环,这会导致问题:
'C:\map' is not recognized as an internal or external command,
operable program or batch file.
虽然'ECHO %%X ^| %jq%' 有效,但似乎'%curl% ^| %jq%' 无效。因此,由于某种原因,一旦解析管道中的 2 个变量,就会出现问题。
好吧,那就不用管了:
SET curl="C:\map with spaces\curl.exe"
SET jq="C:\map with 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 for example
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=6 delims=/" %%A IN ("%url%") DO (
FOR /F "delims=" %%B IN ('%curl% -s http://e.omroep.nl/metadata/aflevering/%%A') DO (
FOR /F "delims=" %%C IN ('ECHO %%B ^| %jq% -R -r -s ".[1+index(\"^(\"): rindex(\"^)\")]"') DO (
FOR /F "delims=" %%D IN ('ECHO %%C ^| %jq% -r .start') DO SET ss=%%D
FOR /F "delims=" %%D IN ('ECHO %%C ^| %jq% -r .eind') DO SET to=%%D
FOR /F "delims=" %%D IN ('ECHO %%C ^| %jq% -r .tijdsduur') DO SET t=%%D
ECHO Start: !ss!
ECHO End: !to!
ECHO Duration: !t!
)
)
)
ENDLOCAL
PAUSE
现在 curl.exe 和 jq.exe 都在一个 for 循环中。起初,这似乎工作正常。 3 个值被回显,但随后出现问题:
parse error: Invalid numeric literal at line 1, column 5
parse error: Invalid numeric literal at line 1, column 5
parse error: Invalid numeric literal at line 1, column 5
parse error: Invalid numeric literal at line 1, column 5
Start: 00:23:13
End: 00:28:40
Duration: 00:05:27
就像我之前说的; for 循环一次只解析和处理 1 行。第 2 行的非 JSON 数据 //epc 导致 for 循环重新开始,如您所见,这是非常错误的。这就是上面代码中 curl 和 jq 之间存在管道的原因。输出 1 单行进行处理。可悲的是,这也不起作用......叹气。
当然,当 curl 和 jq 仍在带有空格的映射中时,使用临时文件是最后的手段,但我更喜欢使用变量,所以我正在尝试解决管道问题。例如,我尝试在 for 循环中使用反引号而不是单引号在 for 循环中使用“usebackq”,但无济于事。
到目前为止,我还没有找到解决方案。有没有人对此行为有解释以及如何解决它?
【问题讨论】:
-
这似乎与
jq或curl毫无关系;相反,它似乎是关于在批处理脚本中正确转义map with spaces文件夹的名称。我认为删除这些标签是有意义的。 -
您是否愿意考虑使用 PowerShell 或其他不需要这种令人费解的语法来正确解析路径的脚本语言?
-
我认为其他脚本语言可以轻松解决这个问题,但在这种情况下我更喜欢使用批处理。
标签: batch-file for-loop pipe environment-variables double-quotes