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



我想使用 set 将 json 文件的内容读入 cmd 变量。我试过这个:

set /p TEXT=<C:myjson.json

但是当我打印值时,我只看到括号,因为有一行新行。

C:Windowssystem32>echo %TEXT%
{
C:Windowssystem32>

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"
}

有很多问题会使您的目标变得困难,如果不是不可能的话。

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

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

test.json(utf-8 编码)

{
"type": "service_accountnline2",
"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_accountnline2","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 文本处理实用程序将文本存储在变量中,无论是否启用延迟扩展,这都有效。 JREPL.BAT 是一个使用 Windows CSCRIPT 引擎的混合 JScript/batch 脚本。它是纯脚本,从XP开始在任何Windows机器上本机运行。

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

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

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

--结果--

str={"type":"service_accountnline2","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 可能是一个非常宝贵的工具。

最新更新