将多个 jq 值传送到“while read -r”循环

如何解决将多个 jq 值传送到“while read -r”循环

我试图找到一种干净的方法,在 while 循环中将 2 个 json 字符串值分配给 2 个变量。我正在使用的循环和输入如下。

输入:

foo='
[
   {
      "name":"name string (more info)","nested_name":{
         "name":"my name","conclusion":"failure","number":11
      }
   },{
      "name":"name string (more info)","nested_name":{
         "name":"my other name","number":13
      }
   }
]'

目前我有以下几点:

echo "$foo" | jq ".[].name,.[].nested_name.name" | while read -r foo bar; do
    # do stuff with foo and bar
done

在迭代 1 中,我想要:

foo = "name string (more info)" 
bar = "my name"

迭代 2:

foo = "name string (more info)" 
bar = "my other name"

然而,这会产生以下不正确的输出

foo = "name 
bar = string (more info)"
foo = "name 
bar = string (more info)"
foo = "my 
bar = name"
foo = "my 
bar = other name"

我一整天都在做这件事,非常感谢任何意见或建议!

解决方法

使用两个 read,每行一个:

#!/usr/bin/env bash

json='
[
   {
      "name":"name string (more info)","nested_name":{
         "name":"my name","conclusion":"failure","number":11
      }
   },{
      "name":"name string (more info)","nested_name":{
         "name":"my other name","number":13
      }
   }
]'


while read -r foo && read -r bar; do
    printf "foo=%s\nbar=%s\n" "$foo" "$bar"
done < <(jq ".[] | .name,.nested_name.name" <<<"$json")

我不得不更改您的 jq 表达式以获得您想要的输出。

还要注意对原始 JSON 文本和循环变量使用不同的名称,使用 here string 代替 echo,并使用文件重定向代替管道;如果 while 的主体设置了以后需要的任何变量,则很有用。


另一种方法是将所有 jq 输出读入一个数组,然后对其进行迭代:

readarray -t lines < <(jq ".[] | .name,.nested_name.name" <<<"$json")
for (( i = 0; i < ${#lines[@]}; i += 2 )); do
    foo=${lines[i]}
    bar=${lines[i+1]}
    printf "foo=%s\nbar=%s\n" "$foo" "$bar"
done
,

如果我模拟一些“CSV 输入”,我可以这样做:(注意 IFS 设置为 ,

echo 'aaa,bbb\nccc,ddd' | while IFS=,read -r x y; do
  echo "x=$x,y=$y"
done

输出:

x=aaa,y=bbb
x=ccc,y=ddd

您可以使用以下 jq 命令生成类似的“CSV 输出”:

jq --raw-output '.[] | "\(.name),\(.nested_name.name)"'

所以我认为它看起来像这样:

echo "$foo" | jq --raw-output '.[] | "\(.name),\(.nested_name.name)"' | while IFS=,read -r foo bar; do
    # do stuff with foo and bar
done
,

这个怎么样:https://jqplay.org/s/4MPWmMjFmM

<?php

namespace App\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class DictionaryCollectionType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder,array $options)
    {
        $builder->add('dictionary',CollectionType::class,[
            'entry_type' => $options['type'],'entry_options' => array('label' => false),'empty_data' => null,'allow_add'    => true,'allow_delete' => true,'label' => false,])
        ->add('save',SubmitType::class,[
            'attr' => ['class' => 'save btn btn-success mt-2','data-toggle' => 'modal','data-target' => '#dictionaryBackdrop','action' => $options['action']],]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => null,'type' => null,'action' => null
        ));
    }
}
,

我更喜欢这样做:

jq --argjson foo "$foo" --null-input --compact-output '$foo[]' | while IFS= read -r item
do
    name="$(jq --argjson item "$item" --null-input --raw-output '$item.name')"
    nested_name="$(jq --argjson item "$item" --null-input --raw-output '$item.nested_name.name')"
    printf 'name is "%s" and nested_name is "%s"\n' "$name" "$nested_name"
done

虽然此方法需要额外调用 jq,但它有几个好处:

  • 如果您需要迭代具有更复杂结构的东西,它很容易扩展。
  • 不使用空格、逗号、引号、制表符和换行符是安全的。
  • 简单易懂,值得信赖。它不涉及任何特殊算法、解析或转义。

如果您想要更简洁一些,这里也可以使用缩写选项。

jq --argjson foo "$foo" -nc '$foo[]' | while IFS= read -r item
do
    name="$(jq --argjson item "$item" -nr '$item.name')"
    nested_name="$(jq --argjson item "$item" -nr '$item.nested_name.name')"
    printf 'name is "%s" and nested_name is "%s"\n' "$name" "$nested_name"
done

再详细一点:

  • 我们使用 --argjson 将我们的 JSON 字符串作为单个参数传入,并使用 --null-input 忽略标准输入。这样我们就不必担心传入过程中的转义或分隔符。
  • 我们使用 --compact-output(或 -c)每行输出一个 JSON 对象。
  • 我们使用 IFS= 来确保我们的 JSON 字符串中的空格和制表符不会被用作分隔符。只有换行符将用作分隔符,并且因为 JSON 字符串中的所有换行符都必须进行转义,所以我们可以确信对于原始 JSON 数组中的每个项目,我们将只循环一次。
  • 我们使用--raw-output(或-r)将JSON字符串的值直接输出到shell变量中。 (如果我们想要 JSON 编码的字符串,我们可以选择省略它。)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?