在 bash 中,创建 json key=filename 和 value=file-contents 的对象,给定标准输入上的路径文件名序列
in bash, create json object of key=filename and value=file-contents given sequence of pathed filenames on stdin
例如,如果 stdin
上的文件名列表是 /etc/alpha.txt
和 /tmp/beta.txt
并且/etc/alpha.txt
包含wibble
并且/tmp/beta.txt
包含fu\nbar
那么我要生成的是
{"/etc/alpha.txt":"wibble","/tmp/beta.txt":"fu\nbar"}
我不会使用任何编程语言。
这是在 Linux OS 上。
我可以安装 jq
.
等实用程序
Léa Gris 的解决方案看起来很准确。谢谢莉亚。 las,我的问题由于不够集中而被关闭。对于那个很抱歉。这只是我在 Whosebug 上的第二个问题!我正在努力让它更专注。这确实是我的确切问题。我正在尝试使 https://cyber-dojo.org 中的核心运行器服务更快一些。
我的尝试卡在了在 jq -s add
之前放什么。
这是一个假设 jq 和 bash 或 bash-like shell 的选项:
while read -r d
do
(cd "$d"; find . -type f -maxdepth 1) | while read -r f ; do
echo $d $'\t' $(sed 's,^./,,' <<< "$f")
done
done | jq -Rn '[inputs | split("\t") | {(.[0]): .[1]}] | add'
参考,如果不想用jq:
#!/bin/bash
gulp() {
echo $(sed -E ':a;N;$!ba;s/\r{0,1}\n/\n/g' )
}
while read f1 && read f2; do
key=$(gulp $f1)
val=$(gulp $f2)
echo "{\"$f1\":\"$key\",\"$f2\":\"$val\"}"
done
"gulp" 子例程读取文件并将换行符转换为文字“\n”。然后脚本的主要部分只是一次从标准输入读取两行。
这里是:
#!/usr/bin/env bash
files=('alpha.txt' 'beta.txt' 'delta with space name.txt')
# Filling sample files
printf 'wibble' >'alpha.txt'
printf 'fu\nbar' >'beta.txt'
cat >'delta with space name.txt' <<'EOF'
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
EOF
# Stream the test files names (1 per line)
printf '%s\n' "${files[@]}" |
xargs -L 1 -I {} jq -sR --arg key {} '{ ($key): .}' {} | jq -s 'add'
xargs -L 1 -I {}
:通过传递 stdin
中的每一行来执行命令,同时用文件名替换大括号。
xargs
然后运行jq
命令创建文件对象的文件名键和值内容:
jq -sR --arg key {} '{ ($key): .}' {}
最后,JSON 对象流通过管道传输到最终的 jq -s 'add'
以重新 assemble 它,成为具有 "key": "value"
对的合并对象:
jq -s 'add'
最后是所有这些的实际输出:
{
"alpha.txt": "wibble",
"beta.txt": "fu\nbar",
"delta with space name.txt": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n"
}
正在用一个 jq
:
处理所有文件
xargs -I {} jq -sR '{(input_filename):.}' {} | jq -s add
使用input_filename
的注意事项来自man jq
:
input_filename
Returns the name of the file whose input is currently being filtered. Note that this will not work well unless jq is running in a UTF-8 locale.
例如,如果 stdin
上的文件名列表是 /etc/alpha.txt
和 /tmp/beta.txt
并且/etc/alpha.txt
包含wibble
并且/tmp/beta.txt
包含fu\nbar
那么我要生成的是
{"/etc/alpha.txt":"wibble","/tmp/beta.txt":"fu\nbar"}
我不会使用任何编程语言。
这是在 Linux OS 上。
我可以安装 jq
.
Léa Gris 的解决方案看起来很准确。谢谢莉亚。 las,我的问题由于不够集中而被关闭。对于那个很抱歉。这只是我在 Whosebug 上的第二个问题!我正在努力让它更专注。这确实是我的确切问题。我正在尝试使 https://cyber-dojo.org 中的核心运行器服务更快一些。
我的尝试卡在了在 jq -s add
之前放什么。
这是一个假设 jq 和 bash 或 bash-like shell 的选项:
while read -r d
do
(cd "$d"; find . -type f -maxdepth 1) | while read -r f ; do
echo $d $'\t' $(sed 's,^./,,' <<< "$f")
done
done | jq -Rn '[inputs | split("\t") | {(.[0]): .[1]}] | add'
参考,如果不想用jq:
#!/bin/bash
gulp() {
echo $(sed -E ':a;N;$!ba;s/\r{0,1}\n/\n/g' )
}
while read f1 && read f2; do
key=$(gulp $f1)
val=$(gulp $f2)
echo "{\"$f1\":\"$key\",\"$f2\":\"$val\"}"
done
"gulp" 子例程读取文件并将换行符转换为文字“\n”。然后脚本的主要部分只是一次从标准输入读取两行。
这里是:
#!/usr/bin/env bash
files=('alpha.txt' 'beta.txt' 'delta with space name.txt')
# Filling sample files
printf 'wibble' >'alpha.txt'
printf 'fu\nbar' >'beta.txt'
cat >'delta with space name.txt' <<'EOF'
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
EOF
# Stream the test files names (1 per line)
printf '%s\n' "${files[@]}" |
xargs -L 1 -I {} jq -sR --arg key {} '{ ($key): .}' {} | jq -s 'add'
xargs -L 1 -I {}
:通过传递 stdin
中的每一行来执行命令,同时用文件名替换大括号。
xargs
然后运行jq
命令创建文件对象的文件名键和值内容:
jq -sR --arg key {} '{ ($key): .}' {}
最后,JSON 对象流通过管道传输到最终的 jq -s 'add'
以重新 assemble 它,成为具有 "key": "value"
对的合并对象:
jq -s 'add'
最后是所有这些的实际输出:
{
"alpha.txt": "wibble",
"beta.txt": "fu\nbar",
"delta with space name.txt": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n"
}
正在用一个 jq
:
处理所有文件
xargs -I {} jq -sR '{(input_filename):.}' {} | jq -s add
使用input_filename
的注意事项来自man jq
:
input_filename
Returns the name of the file whose input is currently being filtered. Note that this will not work well unless jq is running in a UTF-8 locale.