使用sed进行内联替换部分匹配行

时间:2017-10-23 12:04:35

标签: bash sed

我有一个.md文件,其中包含对其他.md文件的多个引用,其形式为:

[Another file](dir/file.md)
[And another file](dir2/anotherfile.md)
[Yet another file](dir3/yetanotherfile.md)

此内联替换的适当sed命令是什么:

[Another file](pdf/dir1/file.pdf)
[And another file](pdf/dir2/anotherfile.pdf)
[Yet another file](pdf/dir3/yetanotherfile.pdf)

我知道如何使用特定模式捕获行,例如通过

sed -rn '/\(.+\.md\)/p' README.md 

但是我无法适当地操作捕获组来执行转换。

THX。

4 个答案:

答案 0 :(得分:2)

尝试以下方法:

sed -re 's#\[([^]]+)\]\(([^\)]+)\.md\)#[\1](pdf/\2.pdf)#g'

这将匹配整个链接表达式,并将*.md替换为pdf/*.pdf。这也将匹配某处的链接 - 不仅仅是

如果您要更新文件的内容,请使用-i标记:

sed -re 's#\[([^]]+)\]\(([^\)]+)\.md\)#[\1](pdf/\2.pdf)#g' -i README.md

输入:

[Another file](dir/file.md)
[And another file](dir/anotherfile.md)
[Yet another file](dir/yetanotherfile.md)

输出:

[Another file](pdf/dir/file.pdf)
[And another file](pdf/dir/anotherfile.pdf)
[Yet another file](pdf/dir/yetanotherfile.pdf)

答案 1 :(得分:2)

修改:您应该更喜欢与完整链接匹配的Attie's solution。我将留下可能解释更多细节的解决方案。

您需要将要在捕获组中的输出中重现的部分分组,然后使用反向引用以替换模式引用它们。

使用-r(在GNU sed中)或-E(在BSD sed或最近的GNU sed中)标记使捕获组更具可读性,因为您不必转义括号。< / p>

在您的情况下,您想捕获没有扩展名的文件名。

这是我将使用的命令(其中+是分隔符,而不是与文件路径分隔符冲突的通常/):

sed -E 's+]\((.*)\.md\)+](pdf/\1.pdf)+g'

POC:

$ echo "[Another file](dir/file.md)
> [And another file](dir/anotherfile.md)
> [Yet another file](dir/yetanotherfile.md)" | sed -E 's+]\((.*)\.md\)+](pdf/\1.pdf)+g'
[Another file](pdf/dir/file.pdf)
[And another file](pdf/dir/anotherfile.pdf)
[Yet another file](pdf/dir/yetanotherfile.pdf)

答案 2 :(得分:0)

更强大的 awk 解决方案:

awk -F'[()]' '{ $2="(pdf/"substr($2,1,length($2)-2)"pdf)"; $0=$1$2 }1' README.md

输出:

[Another file](pdf/dir/file.pdf)
[And another file](pdf/dir/anotherfile.pdf)
[Yet another file](pdf/dir/yetanotherfile.pdf)

答案 3 :(得分:0)

另一个使用sed whithout -r或-E选项

sed 's/\([^(]*(\)\([^.]*.\).*/\1pdf\/\2pdf)/' infile