grep:组捕获

lst*_*kov 51 regex linux bash grep

我有以下字符串:

{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}
Run Code Online (Sandbox Code Playgroud)

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

我试过了

grep -Eo "\"scheme_version\":(\w*)"
Run Code Online (Sandbox Code Playgroud)

然而它又回来了

"scheme_version":1234
Run Code Online (Sandbox Code Playgroud)

我该怎么做?我知道我可以添加sed调用,但我更愿意用单个grep来实现.

Sie*_*geX 62

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

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

  • @Stipa没有PCRE支持你不能用grep做你想要的,因为它不支持反向引用,即`\ 1` (5认同)
  • 当您有多个命名组时,每个组都会在新行中输出。有没有办法将其打印在同一行上?例如 `cat ~/mydoc | grep -Po '(?&lt;=blah"&gt;)[^&lt;]*|(?&lt;=bleh"&gt;&lt;/span&gt;)[^&lt;]*'` 在不同的行中打印捕获的内容。 (2认同)

pot*_*ong 52

这可能对你有用:

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

对不起它不是grep,所以如果你愿意,请忽略这个解决方案.

或坚持使用grep并添加:

grep -Eo "\"scheme_version\":(\w*)"| cut -d: -f2
Run Code Online (Sandbox Code Playgroud)


Mar*_*ain 39

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

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

$ cat tmp | jq .scheme_version
1234
Run Code Online (Sandbox Code Playgroud)

  • 如何在不了解jq的情况下在生活中发挥作用.哇.谢谢! (3认同)

Cla*_*zow 25

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

$ grep -Po 'scheme_version":\K[0-9]+'
Run Code Online (Sandbox Code Playgroud)

这在匹配后重新开始匹配过程scheme_version":,并且往往具有比正向后观更好的性能.比较regexp101上的两个表明复位匹配启动方法需要37步和1毫秒,而正向后看方法需要194步和21毫秒.

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


ken*_*orb 5

为了避免使用GNUgrep可用的PCRE功能,但BSD版本没有此功能,可以使用另一种方法,例如grepripgrep

$ rg -o 'scheme_version.?:(\d+)' -r '$1' <file.json 
1234
Run Code Online (Sandbox Code Playgroud)

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

另一个带有Python和json.tool模块的示例可以验证和打印精美:

$ python -mjson.tool file.json | rg -o 'scheme_version[^\d]+(\d+)' -r '$1'
1234
Run Code Online (Sandbox Code Playgroud)

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