0

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

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

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

这是一个行不通的想法,但说明了我所追求的精神:

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

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

有任何想法吗?

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

4

2 回答 2

0

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

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

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

于 2012-07-11T07:38:47.660 回答
0

您的方法 - 使用 - 将$( … )不起作用,因为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命令执行。内部$( … )部分被扩展为仅生成第一个bashs之间的文本(如果它不需要只获得第一个匹配项会简单得多)。 <h1>

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

注意我已经避免需要使用grepusing sed -n; 您可以使用以下命令交替执行相同的操作,并-m可以选择grep将命令限制为第一个匹配项。

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

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

于 2012-07-11T13:05:53.523 回答