坚持在 bash 中将 JSON 作为参数传递

坚持在 bash 中将 JSON 作为参数传递

我知道很多人都问过类似的问题,但我无法使其发挥作用。

我有一个名为Dependencies

Accounts
Aggregates
Blog
Configuration
Contacts
Contents
DataTypes
Forms
Geo
Globalization
Media
Modules
Navigation
Podcast
Seo
Social
Taxonomy
Tracking
Vlog

我有这段代码将其转换为 JSON 数组字符串:

DependenciesPath=/$Organization/Common/Dependencies
mapfile -t DependenciesArray < $DependenciesPath
DependenciesArray+=('Infra')
export dependencies=$(echo '%s\n' "${DependenciesArray[@]}" | jq -R . | jq -s .)

然后我有这个代码将其传递给node.js

node /$Organization/$Repository/LocalizationHelper.js $File $astFile "$dependencies"

问题是我在我的LocalizationHelper.js文件中得到了这个:

[
  "%s\\n Accounts Aggregates Blog Configuration Contacts Contents DataTypes Forms Geo Globalization Media Modules Navigation Podcast Seo Social Taxonomy Tracking Vlog Infra"
]

正如您所看到的,项目并不是彼此分离的,这%s\\n在开始时也是多余的。这就是我想要的(一个有效的 JSON 数组):

[ "Accounts", "Aggregates", "Blog", ...]

我被困在这里了。我应该怎么办?我想const dependencies = JSON.parse(process.argv[4])在我的代码中将其转换为 JavaScript 数组。

答案1

您可以jq直接用来转换文件。无需使用mapfile或生成 shell 数组:

jq -Rn '[ inputs, "Infra" ]' </path/to/Dependencies

例子:

printf '%s\n' apple banana cherry |
    jq -Rn '[ inputs, "Infra" ]'

输出:

[
  "apple",
  "banana",
  "cherry",
  "Infra" 
]

指示读取原始(未加引号)数据,并指示不要-R在管道“之前”读取任何输入 - 将其留给操作员在适当的点进行处理。jq-njqinputs

您可以通过添加标志将输出压缩为一行-c

["apple","banana","cherry","Infra"]

答案2

jq通常是我进行任何 JSON 处理的首选工具,Chris Davies 给出了一个jq应用于此特定问题的很好的示例在他们的回答中

另一个工具,称为jo是专门为在命令行上构建 JSON。使用jo,JSON 数组可以作为$deps来自以下简短 shell 代码的字符串:

deps=$( jo -a <Dependencies )

添加 anInfra作为数组中的最后一个元素可以像这样完成:

deps=$( jo -a <Dependencies | jo -f - "Infra" )

根据问题中给出的数据,这将生成以下 JSON 数组作为字符串$deps

["Accounts","Aggregates","Blog","Configuration","Contacts","Contents","DataTypes","Forms","Geo","Globalization","Media","Modules","Navigation","Podcast","Seo","Social","Taxonomy","Tracking","Vlog","Infra"]

添加-p到最后一次调用jo以生成打印精美的数组。


另请注意此工具的一些限制。以下是 Stéphane Chazelas 的评论:

请注意,它将看起来像数字的字符串视为数字,将空字符串视为null数组[...]@file将加载文件的内容等(请参阅示例printf '%s\n' 1e002 @/etc/shadow @/dev/watchdog 0xDEADBEEF '' '{}' | jo -a)。它不能以这种方式用于任意字符串。

答案3

如果你在一个努谢尔:

open dependencies.txt | lines | to json

如果你想保留在 bash/zsh 中,你也可以使用 nushell 代替 jq:

nu -c 'open dependencies.txt | lines | to json'

答案4

perl

$ perl -CiI -MJSON::PP -le '
    chomp(@lines = <>);
    print encode_json [@lines, "Infra"]' Dependencies
["Accounts","Aggregates","Blog","Configuration","Contacts","Contents","DataTypes","Forms","Geo","Globalization","Media","Modules","Navigation","Podcast","Seo","Social","Taxonomy","Tracking","Vlog","Infra"]

输入以 UTF-8 解码并编码经过encode_json(不是 STDOUT 输出层,应保留在 byte/latin1 模式)以生成 UTF-8 编码的 JSON。

或者,如果使用 OO 接口,则可以跳过这些解码和编码:

perl -MJSON::PP -le '
  chomp(@lines = <>);
  print JSON::PP->new->encode([@lines, "Infra"])' Dependencies

它将按原样传递> 127 的字节。它不会因非 UTF-8 输入而阻塞,但在这些情况下会生成非 UTF-8 JSON。

要根据区域设置的字符编码对输入进行解码并输出 UTF-8 编码的 JSON:

perl -MJSON::PP -Mopen=IN,locale -le '
  chomp(@lines = <>);
  print encode_json [@lines, "Infra"]' Dependencies

您还可以生成 JSON,其中非 ASCII 字符表示为\uXXXX(或\uDXXXX\uDXXXX像往常一样对于 U+FFFF 以上的字符):

perl -MJSON::PP -Mopen=IN,locale -le '
  chomp(@lines = <>);
  print JSON::PP->new->ascii->encode([@lines, "Infra"])' Dependencies

如果输入仅包含 ASCII 字符(如示例中所示),则不会有任何区别,但如果可能存在非英语依赖项名称,则可能需要考虑这一点。

相关内容