Sed动态反向引用替换

时间:2013-10-05 22:35:40

标签: regex bash unix sed awk

我正在尝试使用sed将wikitext转换为乳胶代码。我差不多完成了,但我想自动生成这样的数字标签:

[[Image(mypicture.png)]]

...进入:

\includegraphics{mypicture.png}\label{img-1}

我想继续使用sed。我正在使用的当前正则表达式和bash代码如下:

__tex_includegraphics="\\\\includegraphics[width=0.95\\\\textwidth]{$__images_dir\/"
__tex_figure_pre="\\\\begin{figure}[H]\\\\centering$__tex_includegraphics"
__tex_figure_post="}\\\\label{img-$__images_counter}\\\\end{figure}"

sed -e "s/\[\[Image(\([^)]*\))\]\].*/$__tex_figure_pre\1$__tex_figure_post/g"\

...但我不能让这个计数器增加。有什么想法吗?

从更一般的角度来看,我的问题如下:我可以在sed中使用反向引用来创建一个替换,它对于sed的每个匹配都是不同的吗?这是,每次sed匹配模式时,我可以使用\ 1作为函数的输入并使用此函数的结果作为替换吗?

我知道这是一个棘手的问题,我可能不得不使用AWK。但是,如果有人有解决方案,我将非常感谢他或她的帮助。

2 个答案:

答案 0 :(得分:2)

您可以使用shell功能逐行读取文件,并为每一行使用单独的sed命令。像

这样的东西
exec 0<input_file

while read line; do
    echo $line | sed -e "s/\[\[Image(\([^)]*\))\]\].*/$__tex_figure_pre\1$__tex_figure_post/g"
    __images_counter=$(expr $__images_counter + 1)
done

(但如果一行中有多个匹配项,则无效。)

对于第二部分,我最好的想法是运行sedgrep来查找匹配的内容,然后再次使用匹配函数的值运行sed文本替换为命令。

答案 1 :(得分:2)

这可能适合你(GNU sed):

sed -r ':a;/'"$PATTERN"'/{x;/./s/.*/echo $((&+1))/e;/./!s/^/1/;x;G;s/'"$PATTERN"'(.*)\n(.*)/'"$PRE"'\2'"$POST"'\1/;ba}' file

这将查找shell变量中包含的PATTERN,如果不存在则会打印当前行。如果模式存在,它会在保持空间中递增或计数计数器,然后将所述计数器附加到当前行。然后使用shell变量PRE和POST以及counter替换模式。最后检查当前行是否有进一步的模式情况,并在必要时重复该过程。