Bash - 循环文件并从主密钥文件中的相应密钥中提取 JSON 值

Bash - 循环文件并从主密钥文件中的相应密钥中提取 JSON 值

我正在尝试制作一个 bash 脚本,该脚本循环遍历包含文件列表的文件(因此它会遍历每个文件)。当文件打开时,我想使用另一个程序 (jq) 从 JSON 文件的键值对中提取值。这是我到目前为止正在处理的内容,保持非常基本,这样我就可以尝试找出哪里出错了。我不关心 jq 命令,我已经让它工作了,我可以循环遍历所有文件并提取单个键的值,但这最终变得非常乏味,因为我必须手动更改它对于每个键。

长话短说: “master” 是包含我想要打开的每个 JSON 文件的完整路径的文件。“key.txt” 是包含这些 JSON 文件中所有可能键的文件。$KEY 是 jq 的语法,用于在打开的文件中搜索该特定键并返回该键的值。我想打开主列表中的文件,循环遍历所有可能的键,并将这些键的值返回到名为“list.txt”的文本文件中。

任何帮助将不胜感激。

#!/bin/bash

master="path/masterlist.txt"
while read master
do
        for KEY in 'key.txt'
        do
                jq '. .'$KEY'' $f
                echo $KEY
        done >> list.txt
        echo $master
done < list.txt

答案1

这是我在获得更多经验后重新审视旧答案jq

问题中的用户说

我不关心 jq 命令 [...]

...但事实上,jq命令是让这项工作高效进行的关键。

回顾一下:用户想要提取某个文本文件 .txt 中列出的所有键的所有值keys.txt。他们希望对另一个文件 .txt 中列出的所有 JSON 文件执行此操作list.txt

要使用 、 、、、 从一组文件 、、 、 中获取一组键 、ab、的所有(已解码)值,您可以这样做:cfile1file2file3jq

jq -r '.[$ARGS.positional[]] // empty' file1 file2 file3 --args a b c

这会将用作键的字符串传递给jq,后者接受它们作为数组中的元素$ARGS.positional。该数组被扩展,其元素用作从输入获取值的键。在这里,empty如果键的值不存在或为,我选择不返回任何内容 ( ) null

围绕该操作内核添加 shell 管道,假设文件列表和键列表都可以是任意长,并且这两个文件包含根据需要引用的行:

xargs sh -c '
    xargs jq -r ".[\$ARGS.positional[]] // empty" "$@" --args <keys.txt
' sh <list.txt >result.txt

这将获取文件名列表并调用一个简短的内联 shell 脚本来批量处理这些文件。内联脚本使用给定的文件名 ( ) 和从键列表中读取的键集xargs进行调用。jq"$@"

结果值列表被写入result.txt


旧答案如下:

阅读完您说您想做的事情后:

master="path/masterlist.txt"

while read json_path; do
    while read key; do
        printf 'File="%s", Key="%s"\n' "$json_path" "$key"
        jq ". .'$key'" "$json_path"
    done <key.txt
done <"$master" >list.txt

读取 JSON 文件列表并依次$master分配每个路径。json_path

key.txt在内循环中,依次读取和分配键key。该实用程序通过参数jq调用,其中参数用当前键的值进行扩展。$json_path. .'$key'$key

所有输出都放入list.txt.

内部循环可能需要进行一些优化。例如,似乎没有必要在外循环的每次迭代中读取所有键。


脚本的带注释版本:

master="path/masterlist.txt"        # this is never used
while read master                   # this will set $master to something from list.txt
do
        for KEY in 'key.txt'        # $KEY will be the string 'key.txt' (nothing else)
        do
                jq '. .'$KEY'' $f   # $f is empty
                echo $KEY
        done >> list.txt            # better to >list.txt after "done" of outer loop
        echo $master
done < list.txt                     # you probably don't want to read from this file

答案2

通过阅读您发布的脚本,我认为$f分配不正确。此外,命令中的引用jq可能会导致问题。事实上,您正在尝试在 while 循环中读取一个裸字,该循环也可能在尝试将其追加到循环内部的同时尝试master读入。list.txtlist.txt

#!/bin/bash

master="path/masterlist.txt"

cat $master | while read f; do
    for KEY in 'key.txt'; do
        echo $(jq ". .'$KEY'" $f) >> list.txt
    done
    echo $master
done

这将从文件中获取每一行,并将其分配给循环中的$master变量,然后运行查询,将输出附加到.$fjqlist.txt

相关内容