输出用分号分隔的字符串

时间:2018-11-05 14:52:09

标签: json bash export-to-csv jq

让我们说我们有这个文件:

{
  "persons": [
    {
      "friends": 4,
      "phoneNumber": 123456,
      "personID": 11111
    },
    {
      "friends": 2057,
      "phoneNumber": 432100,
      "personID": 22222
    },
    {
      "friends": 50,
      "phoneNumber": 147258,
      "personID": 55555
    }
  ]
}

我现在想提取人员1111122222333334444455555的电话号码,以分号分隔的字符串:

123456;432100;;;147258

正在运行

cat persons.txt | jq ".persons[] | select(.personID==<ID>) | .phoneNumber"

对每个<ID>进行一次操作,然后将结果与;粘合在一起,这非常慢,因为它必须为每个ID(以及我想要的其他字段)重新加载文件提取)。

在单个查询中将其串联:

 cat persons.txt | jq "(.persons[] | select(.personID==11111) | .phoneNumber), (.persons[] | select(.personID==22222) | .phoneNumber), (.persons[] | select(.personID==33333) | .phoneNumber), (.persons[] | select(.personID==44444) | .phoneNumber), (.persons[] | select(.personID==55555) | .phoneNumber)"

这也可以,但是可以提供

123456
432100
147258

所以我不知道缺少哪些字段以及必须插入多少;

3 个答案:

答案 0 :(得分:2)

将示例输入到input.json中,并使用jq 1.6(或具有INDEX / 2的jq),jq的以下调用将产生所需的输出:

jq -r --argjson ids '[11111, 22222, 33333, 44444, 55555]' -f tossv.jq input.json 

假设tossv.jq包含程序:

INDEX(.persons[]; .personID) as $dict
| $ids
| map( $dict[tostring] | .phoneNumber)
| join(";")

程序说明

  1. INDEX / 2产生一个用作字典的JSON对象。由于JSON键必须为字符串,因此必须在上面的第3行中使用tostring

  2. 使用join(";")时,null值实际上变成空字符串。

  3. 如果您的jq没有INDEX / 2,那么现在可能是升级的好时机。否则,您可以通过以下操作来搜索其定义:jq "def INDEX" builtin.jq

答案 1 :(得分:0)

不幸的是,由于我只有jq 1.5,所以我无法测试peak's answer是否有效。这是我昨天晚上想出的:

  • 对于每个分号,添加以下查询

    (\";\" as \$a | \$a)
    
  • 结果命令(抽象):

     cat persons.txt | jq "(<1's phone number>), (\";\" as \$a | \$a), 
     (<2's phone number>), (\";\" as \$a | \$a), ..."
    
  • 结果命令(具体):

    cat persons.txt | jq "(.persons[] | select(.personID==11111) | .phoneNumber), (\";\" as \$a | \$a), 
    (.persons[] | select(.personID==22222) | .phoneNumber), (\";\" as \$a | \$a), 
    (.persons[] | select(.personID==33333) | .phoneNumber), (\";\" as \$a | \$a), 
    (.persons[] | select(.personID==44444) | .phoneNumber), (\";\" as \$a | \$a), 
    (.persons[] | select(.personID==55555) | .phoneNumber)"
    
  • 结果:

    123456
    ";"
    432100
    ";"
    ";"
    ";"
    147258
    
  • 删除换行符和"

    <commandAsAbove> | tr --delete "\n\""
    
  • 结果:

    123456;432100;;;147258
    

别误会我的意思,这比匹克的答案要难看得多,但是昨天对我有用。

答案 2 :(得分:0)

没有jq解决方案:

for i in $(seq 11111 11111 55555)
do
  string=$(grep -B1 "$i" persons.txt | head -1 | sed 's/.* \(.*\),/\1/g')
  echo "$string;" >> output
done
cat output | tr -d '\n' | rev | cut -d';' -f2- | rev > tmp && mv tmp output

这个小脚本将产生您想要的结果,并且如果输入数据变化,您可以快速调整它

cat output
123456;432100;;;147258