研究并替换Word Rtf

时间:2012-10-12 09:34:15

标签: php regex word rtf

我正在开发一个具有邮政邮件工作流程的应用程序。这些邮政邮件是根据我的应用程序业务规则生成的。

模型是html或Rtf,只要用户不用word创建rtf,它就能很好地工作。这不符合规范,但如果不涉及太多工作,我的层次结构将欢迎Word兼容性,它会让我们的客户满意并轻松。

Rtf模型的标签由应用程序值替换。在大多数RTF中,标签不会被拆分,因此搜索和替换可以完美地工作。我希望通过一些修改来处理这个词。

示例数据:[[FooBuzz]]在大多数rtf中没有被分割。

在2003年的单词中:

{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5517131 [[}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2708730 FooBuzz}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5517131 ]]}

他们的话(单词2007)也分裂了Foo {垃圾内部} Buzz。

所以我希望能够完美地处理常见的RTF,并检测标签,即使它们被拆分。

我有2个约束。首先没有回归,其次要保持简单。性能不是问题。

我正在使用symfony 1.4。实际相关研究代码部分:

$regExpression = '/\[\[([^\[\]]*)\]\]/';  

preg_match_all($regExpression, $sTemplate, $outKeys); 

更新:

我想我最需要完善这个正则表达式。我正在研究一些正则表达式,但他们还需要一些改进:

/([\a-zA-Z0-9]+)/  

生产:

[0] => Array
    (
        [0] => \rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5517131 [[
        [1] => \rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2708730 FooBuzz
        [2] => \rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5517131 ]]
    )

更新2:

我仍然有一些正则表达式的问题。它实际上找到了第一个标记值和纯文本。 我不确定在合理的时间内我想要什么。

我需要修改正则表达式,所以她捕获相同的结果,但在[[]]内,实际上它也适用于纯文本。

更难的是我必须能够通过我所需的任何方式捕获所有的样本数据(但不是纯文本)。

对于我的替换正则表达式,它替换我的标签和所有垃圾。我几乎成功了:

/{.*?\[\[.*(?<!\\)\w+\b.*\]\].*?}/

但它太贪心了。我希望与小组{[[} {tag} {]]}匹配,并且匹配{纯文字} {[[} {tag} {]]} {纯文字}

我加了?因为我读它会使。*非贪婪但它不起作用。有任何想法吗 ?

我无法理解这个正则表达式(标签查找名称):

\[\[(\b(?<!\\)\w+\b)\]\]

根据我的理解。它在[[]]里面说,找到任何一个不以后面跟着任何单词字符开头的单词。我是对的吗?

更新3:

抱歉我不清楚。

我的第一个正则表达式旨在在[[FooBuzz]]中捕获FooBuzz。并且抓住[[FooBuzz]]的借口。 因此,在第一个正则表达式中,我只想捕获文本FooBuzz,而忽略其他所有内容(如{} \ eoeoe)。

在第二个地方我必须完全替换[[FooBuzz]]。所以我必须抓住{[[} {FooBuzz}} {]]}而已。

实际上我正在捕捉{纯文字我没有抓住} {[[} {FooBuzz}} {]]}}。看到我必须抓住这里。我抓住了:纯文本我没有抓住[[FooBuzz]]。

对于[[部分,我只需要抓住这个:{\ rtlch \ fcs1 \ af0 \ ltrch \ fcs0 \ insrsid5517131 [[}。我猜那是因为他找不到不合适的比赛。所以他处于贪婪模式。并且没有这个数据样本:

{\toto toto}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5517131 [[}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2708730 FooBuzz}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5517131 ]]}{\toto toto}

2 个答案:

答案 0 :(得分:1)

编辑完成后,要查找FooBuzz或任何其他标记,您可以搜索

(?<=\[\[).+?\b(?<!\\)(\w+)\b(?=.+?\]\])

并匹配第一组。

它找到一个完整的单词,而不是\使用否定后瞻(?<!\\),也告诉它需要先于[[,然后是]]

Here示例,您可以看到正确包含FooBar的第一个组:)

为了更好地理解RTF I found a good link,我认为您也可以考虑采用非正则表达式方法,即使在这种情况下我也没有线索。

编辑:

您的上一个正则表达式是错误的,因为它希望\w+恰好位于最后一个方括号之后,它只会匹配[[wordWithoutSpaces]]之类的内容。

第一个“更新1”正则表达式正确匹配整个字符串,你说:“从第一个{开始,找到所有的东西”。我们来看看:

  • {.*?\[\[匹配{[[
  • 之间的所有内容
  • .*(?<!\\)\w+\b匹配[[之后的所有内容,并且在第一个字符\w之前没有反斜杠(可能在这里你想要一个\b之前的负面后卫和{ {1}})
  • \w匹配.*\]\].*?}/与您找到的第一个]]之间的所有内容(非贪婪)

但是如果你想匹配你需要创建不同匹配或不同组的单个部分

修改

由于只有一个正则表达式可以合并两个正则表达式,所以请回答这个问题:

}

{[^{]?[[.(?<=[[).+?\b(?]].?} 将返回2个标签。 1包含正则表达式匹配的数据,第二个包含标记。

然后由于strtr功能,只有与翻译匹配的标签才会被替换。 (工作流程中有3轮)。

答案 1 :(得分:0)

如果有人遇到同样的问题。更好的全球解决方案。 RTF对词语的再现取决于......警察。所以在新罗马时代的[[FooBuzz]]的简单文本搜索工作。但是在Arial中,这个词被爆炸了,你需要一个聪明的正则表达式。

示例:

Police                Text                                RTF
 Times new roman        [[FooBuzz]]                       {\someRtfTags [[FooBuzz]]}
  Arial                 [[FooBuzz]]                         {\hich\af1\dbch\af12\loch\f1 [[Signature}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\insrsid15225063 \hich\af1\dbch\af12\loch\f1 President}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\insrsid1974114\charrsid1974114 \hich\af1\dbch\af12\loch\f1 ]]}

因此请使用Times new Roman作为标签。