Как разобрать JSon в Pure Batch - PullRequest
0 голосов
/ 04 июля 2018

Я пытаюсь понять, как циклы for в пакетных файлах могут перебирать все элементы с параметром / F "delims =", но без токенов. Я пробовал разные способы, но не смог. Во-первых, я знаю, что есть другие способы чтения файлов json, но меня интересует только то, как сделать это в чистом пакетном режиме без каких-либо внешних программ jscript jq и т. Д. Формат JSon, как показано ниже, но количество элементов и порядок они, как правило, различаются.

{"SomeVariableName": "SomeString", "SomeVariableName": "SomeString", "SomeVariableName": "SomeString", "SomeVariableName": "SomeString"}
{"SomeVariableName": "SomeString", "SomeVariableName": "SomeString", "SomeVariableName": "SomeString", "SomeVariableName": "SomeString"}
{"SomeVariableName": "SomeString", "SomeVariableName": "SomeString", "SomeVariableName": "SomeString", "SomeVariableName": "SomeString"}
{"SomeVariableName": "SomeString", "SomeVariableName": "SomeString", "SomeVariableName": "SomeString", "SomeVariableName": "SomeString"}
etc

Но иногда это может быть просто:

"SomeVariableName2": "SomeString2", "SomeVariableName1": "SomeString1",

например у меня так сделано:

SetLocal DisableDelayedExpansion
For /F "delims=" %%c (file.json) Do(
REM iterate through each line
  set "Line=%%c"
  setlocal EnableDelayedExpansion
  set CR=CRLFCRLF
  Set "LineChange1=!Line:~1,-1!"
  for %%d in ("!CR!") do set LineChange2=!LineChange1:", "=%%~d!
  for %%e in (!LineChange4:CRLFCRLF= !) do set /a numtkns+=1
  REM but don't know how to insert the above numtkns in for options as it seems to require a function.
  set LineChange3=!LineChange2:": "==!
  set LineChange4=!LineChange3:"=!
  set /A Countr+=1
  REM this leaves this current line stored in variable LineChange4 as SomeVariableName=SomeStringCRLFCRLFSomeVariableName=SomeStringCRLFCRLFSomeVariableName=SomeStringCRLFCRLFSomeVariableName=SomeString
  )

в качестве альтернативы я мог бы использовать новые строки вместо CRLFCRLF:

SetLocal DisableDelayedExpansion
For /F "delims=" %%c (file.json) Do(
REM iterate through each line
set "Line=%%c"
setlocal EnableDelayedExpansion
for /f %%d in ('copy /Z "%~dpf0" nul') do (
 set "CR=%%d"
)
Set "LineChange1=!Line:~1,-1!"
for %%e in ("!CR!") do set LineChange2=!LineChange1:", "=%%~e!
set LineChange3=!LineChange2:": "==!
set LineChange4=!LineChange3:"=!
set /A Countr+=1

)

Это приводит к многострочному сохранению в переменной LineChange4:

SomeVariableName=SomeString
SomeVariableName=SomeString
SomeVariableName=SomeString
SomeVariableName=SomeString

Как перебрать каждую пару значений ключа и назначить каждое значение переменной с тем же именем, что и ключ. Я видел другой пост, в котором они установили var_% SomeVariableName% = SomeString, но он работает только для первой пары «ключ-значение», и я хочу, чтобы она перебирала все элементы до последнего, даже если количество токенов и их порядок варьируются.

Редактировать: SomeString может быть заголовком с различными символами, поэтому единственными приблизительно известными значениями являются ключи SomeVariableName, которые обычно не имеют пробелов.

Edit2: я изначально не добавил, что я также использовал «Set» LineChange1 =! Line: ~ 1, -1! »Для удаления фигурных скобок, которые обычно идут с файлами JSon.

Ответы [ 3 ]

0 голосов
/ 05 июля 2018

Где файл file.json или загружаемые данные в формате ниже

{"SomeVariableName1": "SomeString1", "SomeVariableName2": "SomeString2", "SomeVariableName3": "SomeString3", "SomeVariableName4": "SomeString4"}
{"SomeVariableName1": "SomeString1", "SomeVariableName2": "SomeString2", "SomeVariableName3": "SomeString3", "SomeVariableName4": "SomeString4"}
{"SomeVariableName1": "SomeString1", "SomeVariableName2": "SomeString2", "SomeVariableName3": "SomeString3", "SomeVariableName4": "SomeString4"}
{"SomeVariableName1": "SomeString1", "SomeVariableName2": "SomeString2", "SomeVariableName3": "SomeString3", "SomeVariableName4": "SomeString4"}

Код ниже работает согласно измененному коду из ответа aschipfl, даже если SomeString содержит пробелы.

:: Define a TAB variable
For /F "delims=" %%A In ('forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x09"') Do Set "TAB=%%A"

rem // also works for ('something that downloads json content')
For /F "delims=" %%c In ('file.json') Do (
    REM // Store current line string:
    Set "LINE=%%c"
    SetLocal EnableDelayedExpansion
    REM // Replace beginning and ending curly brackets:
    Set "LineChange1=!Line:~1,-1!"
    REM // Replace key/value separator ": " by ":" (remove space):
    Set "LineChange2=!LineChange1:": "=":"!"
    REM // Replace CSV ", " with TSV "TAB" (remove space):
    Set "LineChange3=!LineChange2:", "="%TAB%"!"
    REM // Iterate through key/value pairs (separated by Tab):
    For %%P In (!LineChange3!) Do (
        EndLocal
        REM // Split key/value pair:
        For /F "tokens=1* delims=: eol=:" %%Q In ("%%P") Do (
            REM // Remove quotes, assign variable (key = value):
            Set "var_%%~Q=%%~R"
        )
        SetLocal EnableDelayedExpansion
    )
@Echo SomeVariableName1=!var_SomeVariableName1!>>Datafile.txt
@Echo SomeVariableName3=!var_SomeVariableName3!>>Datafile.txt
)
0 голосов
/ 06 июля 2018

Другой, более простой подход:

@echo off
setlocal EnableDelayedExpansion

rem Read the lines of JSon file, removing braces
for /F "delims={}" %%a in (file.json) do (
   set "line=%%~a"
   rem Process each pair of "variable": "string" values
   for %%b in ("!line:": "==!") do echo SET %%b
)

Используя этот входной файл:

{"SomeVariableName1": "Some String 1", "SomeVariableName2": "Some&String<2", "SomeVariableName3": "Some>String|3", "SomeVariableName4": "Some  String  4"}
{"SomeVariableName1": "SomeString1", "SomeVariableName2": "SomeString2", "SomeVariableName3": "SomeString3", "SomeVariableName4": "SomeString4"}
{"SomeVariableName1": "SomeString1", "SomeVariableName2": "SomeString2", "SomeVariableName3": "SomeString3", "SomeVariableName4": "SomeString4"}
{"SomeVariableName1": "SomeString1", "SomeVariableName2": "SomeString2", "SomeVariableName3": "SomeString3", "SomeVariableName4": "SomeString4"}

... это вывод:

SET "SomeVariableName1=Some String 1"
SET "SomeVariableName2=Some&String<2"
SET "SomeVariableName3=Some>String|3"
SET "SomeVariableName4=Some  String  4"
SET "SomeVariableName1=SomeString1"
SET "SomeVariableName2=SomeString2"
SET "SomeVariableName3=SomeString3"
SET "SomeVariableName4=SomeString4"
SET "SomeVariableName1=SomeString1"
SET "SomeVariableName2=SomeString2"
SET "SomeVariableName3=SomeString3"
SET "SomeVariableName4=SomeString4"
SET "SomeVariableName1=SomeString1"
SET "SomeVariableName2=SomeString2"
SET "SomeVariableName3=SomeString3"
SET "SomeVariableName4=SomeString4"
0 голосов
/ 04 июля 2018

Учитывая, что части ключа (SomeVariableName) и значения (SomeString) вашей входной строки не содержат *, ?, <, >, ", они действительно заключены в кавычки "", ключевая часть (SomeVariableName) не содержит :, =, а значение (SomeString) не равно последовательности : + ПРОБЕЛ , может работать следующее:

@echo off
rem // Read JSON file line by line:
for /F "usebackq delims=" %%L in ("file.json") do (
    rem // Store current line string:
    set "LINE=%%L"
    setlocal EnableDelayedExpansion
    rem // Replace key/value separator `": "` by `":"` (remove space):
    set "LINE=!LINE:": "=":"!"
    rem // Trim off opening and closing braces `{`/`}`:
    if defined LINE if "!LINE:~,1!"=="{" set "LINE=!LINE:~1!"
    if defined LINE if "!LINE:~-1!"=="}" set "LINE=!LINE:~,-1!"
    rem // Iterate through key/value pairs (separated by `, `):
    for %%P in (!LINE!) do (
        endlocal
        rem // Split key/value pair:
        for /F "tokens=1* delims=: eol=:" %%Q in ("%%P") do (
            rem // Remove quotes, assign variable (key = value):
            set "%%~Q=%%~R"
        )
        setlocal EnableDelayedExpansion
    )
    endlocal
)

Этот подход изменяет каждую пару ключ / значение "SomeVariableName": "SomeString", удаляя SPACE за разделительным двоеточием :; поскольку : не является стандартным разделителем токенов, в отличие от SPACE и запятой ,, стандартный for цикл может выполнять итерацию для каждой пары ключ / значение как один вещь; for /F loop может затем использоваться для разделения ключа и значения в :; наконец, окружающие кавычки "" каждой части удаляются модификатором ~ , и назначение выполняется.

Переключение отложенное расширение сделано для того, чтобы не было проблем с восклицательными знаками !, появляющимися во входных строках.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...