如何使用 grep -o 搜索和打印每行多个匹配项?

Jak*_*ake 6 grep regular-expression markdown

我有一个 mkdocs 实例,正在编写一个脚本来打印页面中的内部链接。如果每行有多个,我无法让 grep 仅打印匹配项。

这是我目前拥有的:

$ grep -Eon '\[([[:alpha:]]|[[:digit:]]|[[:space:]])*\]\((\/|\.).*\)' /path/to/file.md
10:[foo](../../relative_path/foobar.md) is the path to another file, also see [bar](/absolute/path/foobar.md)
Run Code Online (Sandbox Code Playgroud)

我希望输出如下所示:

10:[foo](../../relative_path/foobar.md)
10:[bar](/absolute/path/foobar.md)
Run Code Online (Sandbox Code Playgroud)

有没有办法在 grep 甚至其他命令(如 awk 或 sed)中执行此操作?

Sta*_*mar 5

grep -Pno "[[[:alnum:]]*]\(.*?\)" /path/to/file.md
Run Code Online (Sandbox Code Playgroud)

或者甚至更好(这甚至可以匹配["foo anotherword"])

grep -Pno "\[([[:alnum:]]*[[:space:]]*)*?\]\(.*?\)"
Run Code Online (Sandbox Code Playgroud)

-P => Perl Regex 用于匹配非贪婪使用 ?

或者,如果不只需要字母数字和空格,而是任何字符意味着

 grep -Pno "\[.*?\]\(.*?\)"
Run Code Online (Sandbox Code Playgroud)


Qua*_*odo 4

\[([[:alpha:]]|[[:digit:]]|[[:space:]])*\]
Run Code Online (Sandbox Code Playgroud)

会匹配[foo],那就可以了。错误在于它来了之后:

\((\/|\.).*\)
Run Code Online (Sandbox Code Playgroud)

在包含正则表达式时需要小心.*,因为它非常非常贪婪!这样就可以匹配了(../../relative_path/foobar.md) is the path to another file, also see [bar](/absolute/path/foobar.md)。连接起来,整行就已经匹配好了。

你应该去

grep -Eon '\[([[:alnum:]]|[[:space:]])*\]\((\.|\/)[^)]*\)'
Run Code Online (Sandbox Code Playgroud)

关键是替换.*为[^)]*,要求后一个正则表达式在右括号出现时停止。另外,我还应用了此更改:

  • [[:alpha:]]|[[:digit:]]可以折叠成[[:alnum:]]

输出:

1:[foo](../../relative_path/foobar.md)
1:[bar](/absolute/path/foobar.md)
Run Code Online (Sandbox Code Playgroud)

(我有1:而不是10:因为它是我文件中的第一行。)