我想使用 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 可能是一个非常宝贵的工具。