从字符串中获取标记,直到它们在shell脚本中耗尽

时间:2016-05-24 14:38:48

标签: bash shell

我有一个shell脚本,它从stdin读取输入字符串,只从输入中获取部分值。输入字符串可以包含任意数量的键/值对,格式如下:

{"input0":"name:/data/name0.csv",
 "input1":"name:/data/name1.csv",
 ....}

所以在上面的例子中,我希望将这些作为我的脚本的输出:

/data/name0.csv
/data/name1.csv
.....

我认为我需要两个while循环,一个需要继续从stdin读取,另一个需要从输入中提取值,直到没有更多。有人能让我知道如何做第二个循环块吗?

2 个答案:

答案 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

仍然没有内循环 - 只需一个循环迭代输入行,主体决定如何处理每一行。