我有一个shell脚本,它从stdin读取输入字符串,只从输入中获取部分值。输入字符串可以包含任意数量的键/值对,格式如下:
{"input0":"name:/data/name0.csv",
"input1":"name:/data/name1.csv",
....}
所以在上面的例子中,我希望将这些作为我的脚本的输出:
/data/name0.csv
/data/name1.csv
.....
我认为我需要两个while循环,一个需要继续从stdin读取,另一个需要从输入中提取值,直到没有更多。有人能让我知道如何做第二个循环块吗?
答案 0 :(得分:1)
如果你有
{"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'
它基本上用正则表达式查找当前行,看看它是否匹配一个形式Begining of line然后是“输入和数字”:“name:/ data / name和number.csv”any然后行结束。 结果是:
/data/name1.csv
/data/name2.csv
/data/name3.csv
/data/name4.csv
...
答案 1 :(得分:1)
这里有一个简单的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 '%s\n' "${BASH_REMATCH[1]}"
done
仍然没有内循环 - 只需一个循环迭代输入行,主体决定如何处理每一行。