如何使用set命令将json文件传递到命令行变量

时间:2019-06-04 12:10:12

标签: batch-file cmd command-line

我想使用set将json文件的内容读取到cmd变量中。我尝试过:

set /p TEXT=<C:\myjson.json

但是当我打印值时,由于有新行,所以我只能看到括号。

C:\Windows\system32>echo %TEXT%
{

C:\Windows\system32>

JSON看起来像这样:

{
  "type": "service_account",
  "project_id": "myproject",
  "private_key_id": "sfackq0355ggeskvcPAFKCADACsdfa",
  "private_key": "-----BEGIN PRIVATE KEY-----  AAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q==",
  "client_email": "myemail@mydomain.com",
  "client_id": "45844444558569745",
  "auth_uri": "url goes here",
  "token_uri": "another url here"
}

1 个答案:

答案 0 :(得分:1)

有很多问题使您的目标难以实现,即使不是不可能通过批次实现。

  • 一个JSON文件可能被编码为UTF-8,很难批量处理。
  • SET /P只能读取一行或1021个字符,以先到者为准。
  • FOR /F可用于读取多行,并且这些值可以串联在一起。但是串联需要两个选项之一,每个选项都有自己的问题
    • 可以使用正常的百分号扩展,但是如果数据中还包含&文字,那么|<"等有毒字符可能会引起问题。同样,扩展百分比至少需要一个CALL,这可能导致加引号的^字符加倍。
    • 可以使用延迟的扩展,但是除非数据先被转义,否则FOR /F扩展将破坏数据中的!并可能破坏^
      • 使用批处理转义!需要进行百分比扩展,这又可能导致毒字问题。
  • 批处理(cmd.exe)仅可用于最大长度为8191个字符的环境变量。操作系统可以处理更大的数据,但批处理不能使用这么大的值。此批次限制根本没有解决方法。

下面是您的示例JSON,添加了一些其他字符以介绍上述所有复杂情况(长度限制除外)。

test.json (utf-8编码)

{
  "type": "service_account\nline2",
  "project_id": "myproject €! \"<^>\"",
  "private_key_id": "sfackq0355ggeskvcPAFKCADACsdfa",
  "private_key": "-----BEGIN PRIVATE KEY-----  AAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q==",
  "client_email": "myemail@mydomain.com",
  "client_id": "45844444558569745",
  "auth_uri": "url goes here ^",
  "token_uri": "another url here ^"
}

假设您的JSON为<8191个字符,并且编码为UTF-8(或ASCII),那么下面的纯批处理代码将起作用。

@echo off
setlocal enableDelayedExpansion

:: Create a linefeed variable
set ^"LF=^
%= Generates a linefeed character =%
^"

:: Save active code page
for /f "tokens=2 delims=:." %%P in ('chcp') do set CHCP=%%P

:: Set active code page to UTF-8
chcp 65001 >nul

:: Read the file into str
set "str="
for /f usebackq^ delims^=^ eol^= %%A in ("test.json") do call :StoreLine

:: Restore active code page
chcp %CHCP% >nul

:: Show the result
set str

exit /b


:StoreLine
:: Safely escapes all ^ as ^^ and ! as ^! before appending %ln%!LF! to !str!
setlocal disableDelayedExpansion
for %%. in (.) do set "ln=%%A"
set "ln=%ln:"=""%"
set "ln=%ln:^=^^%"
set "ln=%ln:!=^!%"
endlocal & set "ln=%ln%" !
set "str=!str!!ln:""="!!LF!"
exit /b

如果您不关心保留格式空格,那么下面的简化代码将起作用(我也删除了注释)。请注意,删除了换行符,前导空格和制表符,但保留了行上的其他空白。

@echo off
setlocal enableDelayedExpansion

for /f "tokens=2 delims=:." %%P in ('chcp') do set CHCP=%%P
chcp 65001 >nul
set "str="
for /f "usebackq tokens=*" %%A in ("test.json") do call :StoreLine
chcp %CHCP% >nul

set str

exit /b


:StoreLine
:: Safely escapes all ^ as ^^ and ! as ^! before appending %ln%!LF! to !str!
setlocal disableDelayedExpansion
for %%. in (.) do set "ln=%%A"
set "ln=%ln:"=""%"
set "ln=%ln:^=^^%"
set "ln=%ln:!=^!%"
endlocal & set "ln=%ln%" !
set "str=!str!!ln:""="!"
exit /b

-输出-

str={"type": "service_account\nline2","project_id": "myproject €! \"<^>\"","private_key_id": "sfackq0355ggeskvcPAFKCADACsdfa","private_key": "-----BEGIN PRIVATE KEY-----  AAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q==","client_email": "myemail@mydomain.com","client_id": "45844444558569745","auth_uri": "url goes here ^","token_uri": "another url here ^"}

以上任一纯批处理解决方案都要求启用延迟扩展。可以编写其他代码来跨ENDLOCAL障碍传递变量。但是我不会打扰。

您可以使用我的JREPL.BAT text processing utility将文本存储在变量中,并且无论是否启用延迟扩展都可以使用。 JREPL.BAT是使用Windows CSCRIPT引擎的混合JScript /批处理脚本。它是纯脚本,可​​以从XP开始在任何Windows计算机上本地运行。

call jrepl.bat "^" "" /f "test.json|utf-8" /rtn str

您可以使用查找/替换功能完全删除所有格式的空白。

call jrepl "\q[\c\q]*\q|\s" "$&|" /m /xseq /t "|" /f "test.json|utf-8" /rtn str

-结果-

str={"type":"service_account\nline2","project_id":"myproject €! \"<^>\"","private_key_id":"sfackq0355ggeskvcPAFKCADACsdfa","private_key":"-----BEGIN PRIVATE KEY-----  AAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q==","client_email":"myemail@mydomain.com","client_id":"45844444558569745","auth_uri":"url goes here ^","token_uri":"another url here ^"}

可以修改/F参数以支持几乎所有编码。在我的计算机上,如果未指定编码,则JREPL(CSCRIPT)默认为Windows-1252。

现在,我不建议仅出于此目的而获取JREPL.BAT。但是JREPL是一个非常强大的文本处理工具。如果您经常发现自己想批量处理文本或文件,那么JREPL可能是非常宝贵的工具。