在 grep 匹配中替换多次出现的字符

Substituting multiple occurrences of a character inside a grep match

我正在尝试使用 TextWrangler 获取一堆文本文件,匹配某些尖括号标签内的所有内容(到目前为止还不错),并且对于 每个 匹配,替换特定字符与另一个字符的所有匹配项。

例如,我想要像

xx+xx <f>bar+bar+fo+bar+fe</f> yy+y <f>fee+bar</f> zz

匹配 <f></f> 中的所有内容,然后将所有 + 替换为 *(但仅在 "f" 标签内)。

xx+xx <f>bar*bar*fo*bar*fe</f> yy+y <f>fee*bar</f> zz

我想我可以很容易地将包含 + 的 "f" 标签与

这样的表达式相匹配
<f>[^<]*\+[^<]*</f>

但我不知道如何为每个匹配项只替换一个字符子类。我事先不知道每个标签中有多少个 +。 我想我应该 运行 为第一个正则表达式的所有匹配项设置一个正则表达式,但我不太确定该怎么做。

(换句话说,我想匹配所有 +,但只匹配特定的尖括号标签内)。

有人有提示吗?

非常感谢, 丹妮尔

如果您可以使用 awk 解决方案:

$ awk '{
    while ( match([=10=],/<f>[^<]*\+[^<]*<\/f>/) ) {
        tgt = substr([=10=],RSTART,RLENGTH)
        gsub(/\+/,"*",tgt)
        [=10=] = substr([=10=],1,RSTART-1) tgt substr([=10=],RSTART+RLENGTH)
    }
    print
}' file
xx+xx <f>bar*bar*fo*bar*fe</f> yy+y <f>fee*bar</f> zz

以上内容在任何 UNIX 机器上使用任何 shell 中的任何 awk 都可以工作。它依赖于每个 <f>...</f> 中没有 <,如示例代码所示。如果可以,则将其包含在您的示例中,我们可以调整脚本来处理它:

$ awk '{
    gsub("</f>",RS)
    while ( match([=11=],/<f>[^\n]*\+[^\n]*\n/) ) {
        tgt = substr([=11=],RSTART,RLENGTH)
        gsub(/\+/,"*",tgt)
        [=11=] = substr([=11=],1,RSTART-1) tgt substr([=11=],RSTART+RLENGTH)
    }
    gsub(RS,"</f>")
    print
}' file
xx+xx <f>bar*bar*fo*bar*fe</f> yy+y <f>fee*bar</f> zz