我有一个 shell 脚本,它从 stdin 读取输入字符串,只从输入中获取部分值。 输入字符串可以具有任意数量的键/值对,格式如下:
{"input0":"name:/data/name0.csv",
"input1":"name:/data/name1.csv",
....}
所以在上面的例子中,我想将这些作为我的脚本的输出:
/data/name0.csv
/data/name1.csv
.....
我想我需要两个 while 循环,一个需要继续从 stdin 读取,另一个需要从输入中提取值,直到没有更多。 有人可以让我知道如何做第二个循环块吗?
如果你有
{"input0":"name:/data/name0.csv",
"input1":"name:/data/name1.csv",
....}
在文件abc.in
中,您可以使用名为 sed 的命令执行以下操作来解析输入:
cat abc.in | sed 's/.*"input[0-9]+":"name:(/data/name[0-9]+.csv)".*$/1/g'
它基本上使用正则表达式查找当前行,并查看它是否匹配以下形式之一 行首 然后是任何东西"输入和一个数字":"名称:/数据/名称和一个数字.csv"任何东西,然后是行尾。结果是:
/data/name1.csv
/data/name2.csv
/data/name3.csv
/data/name4.csv
...
一个简单的 BashFAQ #1 循环在这里工作,jq
将字符串预处理为面向行的内容:
while read -r value; do
echo "${value#name:}"
done < <(jq -r '.[]')
也就是说,您实际上可以在jq
中完成整个操作,而完全没有bash;以下内容将给定的输入直接转换为所需的输出(给定jq
1.5或更高版本):
jq -r '.[] | sub("name:"; "")'
如果你真的想以脆弱的方式做事,而不是利用JSON解析器,你也可以这样做:
# This is evil: Will fail very badly if input formatting changes
content_re='"name:(.*)"'
while read -r line; do
[[ $line =~ $content_re ]] && printf '%sn' "${BASH_REMATCH[1]}"
done
仍然不需要内部循环 - 只需要一个循环遍历输入行,由主体确定如何处理每一行。