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

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

我有一个 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)

我希望输出看起来像这样:

10:[foo](../../relative_path/foobar.md)
10:[bar](/absolute/path/foobar.md)

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

答案1

grep -Pno "[[[:alnum:]]*]\(.*?\)" /path/to/file.md

或者甚至更好(这甚至会匹配[“foo 另一个词”]

grep -Pno "\[([[:alnum:]]*[[:space:]]*)*?\]\(.*?\)"

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

或者如果不想要只有字母数字和空格但是任何字符方法

 grep -Pno "\[.*?\]\(.*?\)"

答案2

\[([[:alpha:]]|[[:digit:]]|[[:space:]])*\]

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

\((\/|\.).*\)

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

你应该去

grep -Eon '\[([[:alnum:]]|[[:space:]])*\]\((\.|\/)[^)]*\)'

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

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

输出:

1:[foo](../../relative_path/foobar.md)
1:[bar](/absolute/path/foobar.md)

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

答案3

grep -on '\[[^]]*\]([^)]*)'

对于你的情况来说可能就足够了。您真的需要限制[...]and中可能出现的字符吗(...)

如果您希望要求内部部分[...]仅由数字或空格组成,并且内部部分(...)以 a/或 a开头.,则只需:

grep -on '\[[[:alnum:][:space:]]*\]([./][^)]*)'

无论如何,请注意,[^)]*而不是.*)as.*会吞掉结尾以及该行)最右边的所有内容。)

这里不需要-E's|交替运算符。要匹配单个字符,可以使用[set]方括号表达式,其中set可以包含多个字符或字符类(此处为和 的[:alnum:]缩写)。[:alpha:][:digit:][:space:]

答案4

需要使用非贪婪的grep

添加?.*((\/|\.).*?\)

grep -Pon '\[([[:alpha:]]|[[:digit:]]|[[:space:]])*\]\((\/|\.).*?\)' /path/to/file.md

10:[foo](../../relative_path/foobar.md)
10:[bar](/absolute/path/foobar.md)
  • -P以获得非贪婪的支持。正则表达式应该是 perl 语法

相关内容