Safer way to parse curl output?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
SIMMS7400
Posts: 546
Joined: 07 Jan 2016 07:47

Safer way to parse curl output?

#1 Post by SIMMS7400 » 29 Aug 2023 07:31

HI All -

I have the following piece of code that is working as expected.

Code: Select all

FOR /F "tokens=2,4 delims=:," %%A IN ('
	curl --location --request POST "%IDCS_URL%/oauth2/v1/device" ^
	--header "Content-Type: application/x-www-form-urlencoded;charset=utf-8" ^
	--data-urlencode "response_type=device_code" ^
	--data-urlencode "scope=urn:opc:idm:__myscopes__  offline_access" ^
	--data-urlencode "client_id=%CLIENT_ID%"
') DO (
	ECHO %%A
	SET "DEVICE_ID=%%A"
	ECHO %%B 
	SET "USER_CODE=%%B"
)
pause
Essentially, it's parsing the following output to extract two values:
{"device_code":"f00b07aab09048268c78787c7f878787","user_code":"HFYRBFJF","verification_uri":"https://idcs-zzzzzzzzzzd.identity.cloud ... es_in":300}
However, there may be a time the output changes format, and I want my parsing to be more dynamic. Is there is a better way to always give me the value after "device_code" (f00b07aab09048268c78787c7f878787) and "user_code" (HFYRBFJF)?

mataha
Posts: 35
Joined: 27 Apr 2023 12:34

Re: Safer way to parse curl output?

#2 Post by mataha » 29 Aug 2023 12:16

Not bulletproof, but should get the job done:

Code: Select all

setlocal EnableDelayedExpansion
(set ^"\n=^

) & for /f delims^=^ eol^= %%l in ("curl (...)") do (
    set "line=%%l"
    set "line=!line:~1,-1!"
    for %%n in ("!\n!") do for /f "tokens=1,* delims=:" %%u in ("!line:,=%%~n!") do (
        if "%%~u" equ "device_code" (
            set "DEVICE_ID=%%~v"
        ) else if "%%~u" equ "user_code" (
            set "USER_CODE=%%~v"
        )
    )
)

OJBakker
Expert
Posts: 90
Joined: 12 Aug 2011 13:57

Re: Safer way to parse curl output?

#3 Post by OJBakker » 29 Aug 2023 12:25

You can use the var search/replace syntax on the complete curl-response.

Code: Select all

@echo off
cls
setlocal
set "CurlResp={"device_code":"f00b07aab09048268c78787c7f878787","user_code":"HFYRBFJF","verification_uri":"https://idcs-zzzzzzzzzzd.identity.cloud ... es_in":300}"

rem find value for "device_code", value is doublequoted string
call :FindItemVal CurlResp Device_ID "device_code"

rem find value for "user_code", value is doublequoted string
call :FindItemVal CurlResp User_Code "user_code"

echo Result:
set "Device_ID"
set "User_Code"
endlocal
pause
exit/b

:FindItemVal
setlocal
rem %1 = var name for curl response, %2 = var name for Item, %3 = name for Item to select enclosed in double quot's

call set "Line=%%%1%%"
set "ItemVar=%2"
set "ItemString=%3"

call set "ItemVar=%%Line:*%ItemString%:"=%%"
set "ToRemove=%ItemVar:*"="%"
call set "ItemVar=%%ItemVar:%ToRemove%=%%"

endlocal & set %2=%ItemVar%
exit /b
And the same as above, but now with option for verbose debug-output.

Code: Select all

@echo off
cls
setlocal
set "CurlResp={"device_code":"f00b07aab09048268c78787c7f878787","user_code":"HFYRBFJF","verification_uri":"https://idcs-zzzzzzzzzzd.identity.cloud ... es_in":300}"
rem set "Verbose="
set "Verbose=Y"
if defined Verbose set CurlResp

rem find value for "device_code", value is doublequoted string
call :FindItemVal CurlResp Device_ID "device_code" %Verbose%
if defined Verbose set "Device_ID"

rem find value for "user_code", value is doublequoted string
call :FindItemVal CurlResp User_Code "user_code" %Verbose%
if defined Verbose set "User_Code"

echo Result:
set "Device_ID"
set "User_Code"
endlocal
pause
exit/b

:FindItemVal
setlocal
rem %1 = var name for curl response, %2 = var name for Item, %3 = name for Item to select enclosed in double quot's, %4 means verbose output
set "Verbose=%4"
if defined Verbose (echo begin %0 & echo parameters: %*)

call set "Line=%%%1%%"
set "ItemVar=%2"
set "ItemString=%3"
if defined Verbose (set "LIne" & set "Item")

if defined Verbose echo trimleft
call set "ItemVar=%%Line:*%ItemString%:"=%%"
if defined Verbose set "ItemVar"
rem remove part left of first "
set "ToRemove=%ItemVar:*"="%"
if defined Verbose set "ToRemove"
if defined Verbose echo trimright
call set "ItemVar=%%ItemVar:%ToRemove%=%%"
if defined Verbose set "ItemVar"

if defined Verbose echo end  %0
endlocal & set %2=%ItemVar%
exit /b

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Safer way to parse curl output?

#4 Post by Aacini » 29 Aug 2023 18:09

This is the way I would do it:

Code: Select all

@echo off
setlocal

set "CurlResp={"device_code":"f00b07aab09048268c78787c7f878787","user_code":"HFYRBFJF","verification_uri":"https://idcs-zzzzzzzzzzd.identity.cloud ... es_in":300}"

rem Remove braces
set "CurlResp=%CurlResp:~1,-1%"

rem Change ":" by =
set "CurlResp=%CurlResp:":"==%"

rem Split the line at the commas, and execute a "set" command in each part
set %CurlResp:,= & set %

rem Show results
echo device_code=%device_code%
echo user_code=%user_code%
echo verification_uri=%verification_uri%
Perhaps the simplest way to explain how this works is remove the @echo off line and execute the program...

Output:

Code: Select all

device_code=f00b07aab09048268c78787c7f878787
user_code=HFYRBFJF
verification_uri=https://idcs-zzzzzzzzzzd.identity.cloud ... es_in
Note that this method get the values of all variables in the line with the same format (like verification_uri)

Antonio

SIMMS7400
Posts: 546
Joined: 07 Jan 2016 07:47

Re: Safer way to parse curl output?

#5 Post by SIMMS7400 » 05 Sep 2023 04:32

Thank you so much, Aacini - this way is very slick!!! I'll use this. Thanks again!
Aacini wrote:
29 Aug 2023 18:09
This is the way I would do it:

Code: Select all

@echo off
setlocal

set "CurlResp={"device_code":"f00b07aab09048268c78787c7f878787","user_code":"HFYRBFJF","verification_uri":"https://idcs-zzzzzzzzzzd.identity.cloud ... es_in":300}"

rem Remove braces
set "CurlResp=%CurlResp:~1,-1%"

rem Change ":" by =
set "CurlResp=%CurlResp:":"==%"

rem Split the line at the commas, and execute a "set" command in each part
set %CurlResp:,= & set %

rem Show results
echo device_code=%device_code%
echo user_code=%user_code%
echo verification_uri=%verification_uri%
Perhaps the simplest way to explain how this works is remove the @echo off line and execute the program...

Output:

Code: Select all

device_code=f00b07aab09048268c78787c7f878787
user_code=HFYRBFJF
verification_uri=https://idcs-zzzzzzzzzzd.identity.cloud ... es_in
Note that this method get the values of all variables in the line with the same format (like verification_uri)

Antonio

Post Reply