【问题标题】:JQ JSON CreationJQ JSON 创建
【发布时间】:2019-01-24 16:43:07
【问题描述】:

JSON 创建新手,决定从this question 尝试 JQ。然而,当我尝试实现它时,我收到的只是 JQ 的帮助页面和这些类型的错误:./test.sh: line 43: --: command not found 最后三行。

#!/bin/bash

echo Starting

sensorType="XXX"
sensorLocation="XXX"
sensorCommand="XXXXX"

# Hardware information. 
systemTime=$(date +%d-%m-%Y_%H:%M:%S)
kernalName=$(uname -s)
nodeName=$(uname -i)
kernalRelease=$(uname -r)
kernalVersion=$(uname -v)
machine=$(uname -m)
processor=$(uname -p)
hardwarePlatform=$(uname -i)
operatingSystem=$(uname -o)
timeup=$(uptime)

# Software information.
softVersion=$(XXX version)

JSON_STRING=$( jq -n \
                -- arg systemTime "$systemTime" \
                -- arg sensorType "$sensorType" \
                -- arg sensorLocation "$sensorLocation" \
                -- arg sensorCommand "$sensorCommand" \
                -- arg kernalName "$kernalName" \
                -- arg nodeName "$nodeName" \
                -- arg kernalRelease "$kernalRelease" \
                -- arg kernalVersion "$kernalVersion" \ 
                -- arg machine "$machine" \ 
                -- arg processor "$processor"
                -- arg hardwarePlatform "$hardwarePlatform" \
                -- arg operatingSystem "$operatingSystem" \
                -- arg timeup "$timeup" \
                -- arg softVersion "$softVersion" \
                '{systemTime: $systemTime, sensorType: $sensorType, sensorLocation: $sensorLocation, kernalName: $kernalName, nodeName: $nodeName, kernalRelease: $kernalRelease, machine: $machine, processor: $processor, hardwarePlatform: $hardwarePlatform, operatingSystem: $operatingSystem, timeup: $timeup, softVersion: $softVersion }' )

echo $JSON_STRING

不确定这是否是使用 JQ 的最有效方式,或者是否有更好的方式来实现它。但我很想听听是否有更有效/更简单的方法来实现这一点。

【问题讨论】:

  • 这似乎是您的jq 命令中的错字。 --arg 字段之间不应有空格
  • 谢谢@Inian!
  • 您还缺少processor 行上的反斜杠,这就是导致“找不到命令”错误的原因; hardwarePlatform-- 被视为新命令的开始,而不是 jq 命令的参数。

标签: json bash validation logging jq


【解决方案1】:

使用数组存储参数之前调用jq;由于不需要反斜杠,因此在数组赋值中跨多行分布参数更容易。

jq_args=(
   --arg systemTime "$systemTime"
   --arg sensorType "$sensorType"
   --arg sensorLocation "$sensorLocation"
   --arg sensorCommand "$sensorCommand"
   --arg kernalName "$kernalName"
   --arg nodeName "$nodeName"
   --arg kernalRelease "$kernalRelease"
   --arg kernalVersion "$kernalVersion" 
   --arg machine "$machine"
   --arg processor "$processor"
   --arg hardwarePlatform "$hardwarePlatform"
   --arg operatingSystem "$operatingSystem"
   --arg timeup "$timeup"
   --arg softVersion "$softVersion"
)
JSON_STRING=$( jq -n "${jq_args[@]}" '{
   systemTime: $systemTime,
   sensorType: $sensorType,
   sensorLocation: $sensorLocation,
   kernalName: $kernalName,
   nodeName: $nodeName,
   kernalRelease: $kernalRelease,
   machine: $machine,
   processor: $processor,
   hardwarePlatform: $hardwarePlatform,
   operatingSystem: $operatingSystem,
   timeup: $timeup,
   softVersion: $softVersion 
 }' )

如果您使用支持关联数组的bash 版本,您可以进一步简单地构建jq_args

declare -A x
x=([systemTime]="$systemTime"
   [sensorType]="$sensorType"
   # etc
  )

declare -a jq_args
for k in "${!x[@]}"; do
  jq_args+=(--arg "$k" "${x[$k]}")
done

JSON_STRING=$( jq -n "${jq_args[@]}" ... )

【讨论】:

  • 稍微减少过滤器的小技巧,{ $foo }{ foo: $foo } 相同。所以你可以在所有这些属性上使用它。
  • 有趣的是你应该提到这一点;我昨天在另一个答案中才想起该功能:)
【解决方案2】:

正如@Inian 所指出的,第一个问题是“--”和“arg”之间不应该有空格。

第二个问题是当反斜杠用于续行时(如这里),在反斜杠之后不应有空格:为了使反斜杠用作续行字符,它必须转义(即紧接在前面)换行符。

否则,除了$(XXX version) 等一些奇怪的东西,你应该很高兴,这并不是说没有更好的方法来创建 JSON 对象。有关替代方法的说明,请参阅下一节。

另一种方法的说明

即使键和/或值包含控制字符,也可以使用以下方法:

FMT="%s\0%s\0"
(
printf $FMT systemTime $(date +%d-%m-%Y_%H:%M:%S)
printf $FMT newline "$(echo a; echo b)"
) | jq -sR '[split("\u0000") | range(0;length;2) as $i | {(.[$i]): .[$i + 1]}] | add'

如果已知没有键或值包含文字换行符,则可以使用以下变体,其主要优点是不需要“-s”选项:

(
echo systemTime
date +%d-%m-%Y_%H:%M:%S
echo uname
uname -a
echo softVersion
echo XXX version
) | jq -nR '[inputs as $key | {($key): input}] | add'

【讨论】:

  • 谢谢! @Inian 指出的问题和反斜杠让我明白了。
【解决方案3】:

不确定这是否是使用 JQ 的最有效方式

这里有两种替代方法。第一个基于TSV格式,第二个基于CSV格式。

使用 TSV 格式

以下假设在键或值中均未出现文字制表符或文字换行符。

FMT="%s\t%s\n"
(
printf $FMT systemTime $(date +%d-%m-%Y_%H:%M:%S)
printf $FMT uname "$(uname -a)"
printf $FMT softVersion "XXX version"
) | jq -nR '[inputs | split("\t") | {(.[0]): .[1]}] | add'

使用 CSV 转 JSON 实用程序

如果从键值对的 CSV 文件开始,这里说明的方法可能主要是令人感兴趣的。

在下文中,我们将使用https://github.com/fadado/CSV 上出色的 csv2json 实用程序,其中实际上提供了两个可执行文件。两者都将每个 CSV 行转换为 JSON 数组。我们将使用extended 符号链接到csv2json

(
echo systemTime, $(date +%d-%m-%Y_%H:%M:%S)
echo uname, "$(uname -a)"
echo softVersion, XXX version
) | csv2json 
  | jq -n '[inputs as [$key, $value] | {($key): $value}] | add'

【讨论】:

    【解决方案4】:

    如果您将所有值都作为环境变量,则可以使用env 对象来获取值。然后语法就变得微不足道了。

    systemTime=$(date +%d-%m-%Y_%H:%M:%S) \
    kernalName=$(uname -s) \
    nodeName=$(uname -i) \
    kernalRelease=$(uname -r) \
    kernalVersion=$(uname -v) \
    machine=$(uname -m) \
    processor=$(uname -p) \
    hardwarePlatform=$(uname -i) \
    operatingSystem=$(uname -o) \
    timeup=$(uptime) \
    jq -n 'env | {
        systemTime,
        sensorType,
        sensorLocation,
        kernalName,
        nodeName,
        kernalRelease,
        machine,
        processor,
        hardwarePlatform,
        operatingSystem,
        timeup,
        softVersion 
    }'
    

    【讨论】:

      猜你喜欢
      • 2019-02-13
      • 1970-01-01
      • 2018-01-10
      • 1970-01-01
      • 2018-03-25
      • 2021-02-12
      • 2014-04-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多