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