grep: group capturing



我有以下字符串:

{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}

,我需要得到"scheme version"的值,在这个例子中是1234。

我试过了

grep -Eo ""scheme_version":(w*)"

但是它返回

"scheme_version":1234

我怎样才能做到呢?我知道我可以添加sed调用,但我更喜欢使用单个grep。

您需要使用查看后面的断言,以便它不包含在匹配中:

grep -Po '(?<=scheme_version":)[0-9]+'

这可能适合您:

echo '{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}' |
sed -n 's/.*"scheme_version":([^}]*)}/1/p'
1234

对不起,它不是grep,所以如果你喜欢,忽略这个解决方案。

或者继续使用grep并添加:

grep -Eo ""scheme_version":(w*)"| cut -d: -f2

我建议您使用jq来完成这项工作。jq是一个命令行JSON处理器

$ cat tmp
{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}
$ cat tmp | jq .scheme_version
1234

作为SiegeX建议的正向后查找方法的替代方法,您可以使用K转义序列将匹配起点直接重置为scheme_version":之后。例如,

$ grep -Po 'scheme_version":K[0-9]+'

这将在匹配scheme_version":后重新启动匹配过程,并且往往比正向后看的性能要好得多。在regexp101上比较两者表明,重置匹配开始方法需要37个步骤和1ms,而正面向后看方法需要194个步骤和21ms。

您可以自己比较regex101上的性能,您可以在PCRE文档中阅读有关重置匹配起点的更多信息。

为了避免使用grep的PCRE特性,该特性在GNU grep中可用,但在BSD版本中没有,另一种方法是使用ripgrep,例如

$ rg -o 'scheme_version.?:(d+)' -r '$1' <file.json 
1234

-r捕获组索引(如$5)和名称(如$foo)。

另一个Python和json.tool模块的例子,可以验证和漂亮打印:

$ python -mjson.tool file.json | rg -o 'scheme_version[^d]+(d+)' -r '$1'
1234

相关:grep可以只输出匹配的指定分组吗?

你可以这样做:

$ echo '{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}' | awk -F ':' '{print $4}' | tr -d '}'

改进@potong的答案,它只能得到"scheme_version",您可以使用这个表达式:

$ echo '{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}' | sed -n 's/.*"_id":["]*([^(",})]*)[",}].*/1/p'
scheme_version
$ echo '{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}' | sed -n 's/.*"_rev":["]*([^(",})]*)[",}].*/1/p'
4-cad1842a7646b4497066e09c3788e724
$ echo '{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}' | sed -n 's/.*"scheme_version":["]*([^(",})]*)[",}].*/1/p'
1234

最新更新