根据JSON规范,不必用反斜杠转义正斜杠,但它们可以转义。我有一个JSON文件,其中所有字符串值中的正斜杠都是出于兼容的原因(但不是在键内)转义的:
{
"proto://some/path": "\/\/some\/path"
}但是,jq会自动删除这些反斜杠:
$ echo '{"proto://some/path":"\/\/some\/path"}' | jq -c .
{"proto://some/path":"//some/path"}我需要输出为{"proto://some/path":"\/\/some\/path"}
How我可以告诉 jq to不更改任何字符串值并保留这些反斜杠吗?或者,是否有一种方法只在经过jq后才将这些反斜杠重新添加到值中?
发布于 2023-02-26 20:12:25
如果你能的话我会很惊讶的。jq解码其输入,执行其操作,并将结果对象编码为json。在编码和输出时,它输出用\编码的字符串,而在/s前面有D2S的信息早就丢失了。同样的情况也会发生在最初写\u002f的/s身上。您会发现,出于同样的原因,jq还将1.0重新格式化为1、1e2为100、INF为1.7976931348623157e+308等。
但是,JSON是一种相对容易的文件格式,可以使用perl等手工可靠地处理。
要在所有字符串(对象键除外)中的每个\s之前添加/ S,您可以这样做:
jq... |
perl -0777 -pe '
s{"(?:\\.|.)*?"(\s*:)?}{
$1 ? A14 : A14 =~ s{/}{\\/}gr
}ge'这应该是正确的,即使你有字符串嵌入",S和\s (如{"key": "//\"//\\"})。
作为jq的另一种选择,您可以使用JSON::PP perl模块,它可以被告知转义斜杠(尽管在所有字符串中都是这样):
$ json_pp -json_opt escape_slash < your-file
{"proto:\/\/some\/path":"\/\/some\/path"}如果您已经熟悉perl,那么学习曲线将比必须学习jq语法要小得多。
在任何情况下,尽管JSON格式允许/s作为\/ (或与任何字符类似的\u002f )被转义,但它们并不需要转义。根据我在网上看到的内容,这是允许的,这样就可以通过编写将包含</code>的JSON字符串嵌入到HTML标记中。这就是为什么一些JSON编码器将这些<code>\/</code>编码为<code>/</code>,因为这使得它更易于移植。但是,如果这个JSON不像HTML那样被嵌入,那么它可能并不重要。如果是的话,您很可能希望在任何地方都有这种编码,包括在对象键中。</div>
发布于 2023-02-26 20:13:37
我假设某个进程没有意识到在JSON中编码字符串的必要性,而是插入了他们认为需要存储的文字字符串,而没有对其进行编码。由于反斜杠是转义不需要转义的字符,而且由于没有反斜杠本身转义文字反斜杠,所以当jq用于提取和解码字符串时,或者当它出于其他原因处理文档时,反斜杠看起来会“消失”。
简而言之,正斜杠不一定要转义(逃避它们实际上是一种不操作),但是如果您想将反斜杠保持为文字反斜杠,则反斜杠必须是反斜杠。
下面以递归的方式将文档中所有字符串值中的每个/转换为\\/ (这是用JSON字符串编写\/的方式)。记住,当jq表达式处理数据时,jq解析器已经删除了反斜杠。
jq 'walk(if type == "string" then gsub("/"; "\\/") else . end)' file对于给定的示例文档,这将生成
{
"proto://some/path": "\\/\\/some\\/path"
}从修改后的文档中提取和解码编码的字符串值将为您提供\/\/some\/path:
$ jq 'walk(if type == "string" then gsub("/"; "\\/") else . end)' file | jq -r '."proto://some/path"'
\/\/some\/path如果从零开始创建相同的JSON文档,如下所示:
$ jq -n --arg 'proto://some/path' '\/\/some\/path' '$ARGS.named'
{
"proto://some/path": "\\/\\/some\\/path"
}https://unix.stackexchange.com/questions/737018
复制相似问题