Linux/Cygwin:用其他模式匹配的结果替换模式(sed/find?)



我有一个大型的文档网站,如下所示:
<title>DOCTITLE</title>
<h1>Some Title</h1>

我正在尝试使用Cygwin在每个文件中用Some Title替换DOCTITLE。

更具体地说,我需要从每个文件中提取<h1>标记之间的任何文本,并用提取的文本替换文本字符串"DOCTITLE"。

这里有一个想法不起作用,但它说明了我追求的精神:

find . -name "*html"  
       -exec sed -i 
                's/DOCTITLE/'$(grep "h1" | sed 's/<h1>(.*)</h1>/1/')'/'
'{}' /;

不出所料,这会失败,因为grep没有输入,它会破坏<h1>

有什么想法吗?

感谢您的时间和专业知识!

您的方法——使用$( … )——不会起作用,因为sed-exec参数无法处理该语法。然而,我们可以做的是调用bash为我们做这项工作:

find . -name '*.html' -exec /bin/bash -c 'sed "s/DOCTITLE/$(sed -n ''',<h1>.*</h1>,{s,<h1>(.*)</h1>,1,p;q}''' '''{}''')/" "{}"' ;

外部sed的作用与sed命令的作用完全相同。内部$( … )部分由bash扩展,只生成第一个<h1>之间的文本(如果不需要只获得第一个匹配,则会简单得多)。

具体来说,内部sed默认不打印任何内容(-n),然后对于与正则表达式<h1>.*</h1>匹配的行,它运行s,<h1>(.*)</h1>,1,p;q,即剥离HTML标签,打印结果,然后退出;CCD_ 18确保我们只打印出第一个匹配项。

注意,我使用sed -n避免了使用grep;您可以用下面的命令做同样的事情,-m选项到grep将命令限制为第一个匹配。

find . -name '*.html' -exec /bin/bash -c 'sed "s/DOCTITLE/$(grep -m1 '''<h1>.*</h1>''' '''{}''' | sed '''s,<h1>(.*)</h1>,1,''')/" "{}"' ;

在这两种情况下,都有一些稍微可怕的引用:'''序列将一个引用插入到一个引用字符串中。我们需要引用sed语句,以确保标题中的任何空格都不会引起问题,并且我们需要引用文件名,以便能够处理文件名中的空格。

这可能对你有用(GNU sed):

find . -name "*html" -exec sed -i '$!N;s/DOCTITLE([^n]*n<h1>([^<]*)</h1>)/21/;P;D' {};

这需要首先进行广泛的测试!

最新更新