2008-10-09 70 views
29

我一直在寻找一种方式来删除文本和RTF字符串,并提取文本正则表达式我发现下面的正则表达式:从一个RTF字符串

({\\)(.+?)(})|(\\)(.+?)(\b) 

但是结果字符串具有两个右尖括号“} “

前:{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 MS Shell Dlg 2;}{\f1\fnil MS Shell Dlg 2;}} {\colortbl ;\red0\green0\blue0;} {\*\generator Msftedit 5.41.15.1507;}\viewkind4\uc1\pard\tx720\cf1\f0\fs20 can u send me info for the call pls\f1\par }

后:} can u send me info for the call pls }

关于如何改进正则表达式的想法?

编辑:一个更复杂的字符串,比如这一个不工作:{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 MS Shell Dlg 2;}} {\colortbl ;\red0\green0\blue0;} {\*\generator Msftedit 5.41.15.1507;}\viewkind4\uc1\pard\tx720\cf1\f0\fs20 HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\test\\myapp\\Apps\\\{3423234-283B-43d2-BCE6-A324B84CC70E\}\par }

回答

2

RegexPal,两个}的是那些下面以粗体显示:

{\ RTF1 \ ansi \ ansicpg1252 \ deff0 \ deflang1033 {\ fonttbl {\ f0 \ fnil \ fcharset0 MS Shell Dlg 2;} {\ f1 \ fnil MS Shell Dlg 2;} } {\ colortbl; \ red0 \ green0 \ blue0;} { \ generator Msftedit 5.41.15.1507;} \ viewkind4 \ uc1 \ pard \ tx720 \ cf1 \ f0 \ fs20您是否可以向我发送电话信息pls \ f1 \ par }

我能够通过添加一个加号,正则表达式来解决第一个花括号:

({\\)(.+?)(}+)|(\\)(.+?)(\b) 
      ^
    plus sign added here 

,并在年底解决大括号,我这样做:

({\\)(.+?)(})|(\\)(.+?)(\b)|}$ 
          ^
     this checks if there is a curly brace at the end 

我不知道RTF格式的非常好所以这可能并不适用于所有情况,但它适用于你的榜样......

5

我以前用这个和它的工作对我来说:

\\\w+|\{.*?\}|} 

你可能要修剪的结果的两端摆脱多余的空格遗留下来的。

39

在RTF中,{和}标记一个组。组可以嵌套。 \标记控制字的开头。控制字以空格或非字母字符结尾。一个控制字可以有一个数字参数,其间没有任何分隔符。一些控制字也采用以';'分隔的文本参数。这些控制字通常在他们自己的组中。

我想我已经设法制作了一种照顾大多数情况的模式。

\{\*?\\[^{}]+}|[{}]|\\\n?[A-Za-z]+\n?(?:-?\d+)?[ ]? 

虽然在模式上运行时会留下几个空格。


走向低谷的RTF specification(有些),我看到有纯基于正则表达式脱衣舞很多陷阱。最明显的是应该忽略一些组(页眉,页脚等),而其他组应该被渲染(格式化)。

我写了一个Python脚本,应该工作比我的正则表达式以上更好:

def striprtf(text): 
    pattern = re.compile(r"\\([a-z]{1,32})(-?\d{1,10})?[ ]?|\\'([0-9a-f]{2})|\\([^a-z])|([{}])|[\r\n]+|(.)", re.I) 
    # control words which specify a "destionation". 
    destinations = frozenset((
     'aftncn','aftnsep','aftnsepc','annotation','atnauthor','atndate','atnicn','atnid', 
     'atnparent','atnref','atntime','atrfend','atrfstart','author','background', 
     'bkmkend','bkmkstart','blipuid','buptim','category','colorschememapping', 
     'colortbl','comment','company','creatim','datafield','datastore','defchp','defpap', 
     'do','doccomm','docvar','dptxbxtext','ebcend','ebcstart','factoidname','falt', 
     'fchars','ffdeftext','ffentrymcr','ffexitmcr','ffformat','ffhelptext','ffl', 
     'ffname','ffstattext','field','file','filetbl','fldinst','fldrslt','fldtype', 
     'fname','fontemb','fontfile','fonttbl','footer','footerf','footerl','footerr', 
     'footnote','formfield','ftncn','ftnsep','ftnsepc','g','generator','gridtbl', 
     'header','headerf','headerl','headerr','hl','hlfr','hlinkbase','hlloc','hlsrc', 
     'hsv','htmltag','info','keycode','keywords','latentstyles','lchars','levelnumbers', 
     'leveltext','lfolevel','linkval','list','listlevel','listname','listoverride', 
     'listoverridetable','listpicture','liststylename','listtable','listtext', 
     'lsdlockedexcept','macc','maccPr','mailmerge','maln','malnScr','manager','margPr', 
     'mbar','mbarPr','mbaseJc','mbegChr','mborderBox','mborderBoxPr','mbox','mboxPr', 
     'mchr','mcount','mctrlPr','md','mdeg','mdegHide','mden','mdiff','mdPr','me', 
     'mendChr','meqArr','meqArrPr','mf','mfName','mfPr','mfunc','mfuncPr','mgroupChr', 
     'mgroupChrPr','mgrow','mhideBot','mhideLeft','mhideRight','mhideTop','mhtmltag', 
     'mlim','mlimloc','mlimlow','mlimlowPr','mlimupp','mlimuppPr','mm','mmaddfieldname', 
     'mmath','mmathPict','mmathPr','mmaxdist','mmc','mmcJc','mmconnectstr', 
     'mmconnectstrdata','mmcPr','mmcs','mmdatasource','mmheadersource','mmmailsubject', 
     'mmodso','mmodsofilter','mmodsofldmpdata','mmodsomappedname','mmodsoname', 
     'mmodsorecipdata','mmodsosort','mmodsosrc','mmodsotable','mmodsoudl', 
     'mmodsoudldata','mmodsouniquetag','mmPr','mmquery','mmr','mnary','mnaryPr', 
     'mnoBreak','mnum','mobjDist','moMath','moMathPara','moMathParaPr','mopEmu', 
     'mphant','mphantPr','mplcHide','mpos','mr','mrad','mradPr','mrPr','msepChr', 
     'mshow','mshp','msPre','msPrePr','msSub','msSubPr','msSubSup','msSubSupPr','msSup', 
     'msSupPr','mstrikeBLTR','mstrikeH','mstrikeTLBR','mstrikeV','msub','msubHide', 
     'msup','msupHide','mtransp','mtype','mvertJc','mvfmf','mvfml','mvtof','mvtol', 
     'mzeroAsc','mzeroDesc','mzeroWid','nesttableprops','nextfile','nonesttables', 
     'objalias','objclass','objdata','object','objname','objsect','objtime','oldcprops', 
     'oldpprops','oldsprops','oldtprops','oleclsid','operator','panose','password', 
     'passwordhash','pgp','pgptbl','picprop','pict','pn','pnseclvl','pntext','pntxta', 
     'pntxtb','printim','private','propname','protend','protstart','protusertbl','pxe', 
     'result','revtbl','revtim','rsidtbl','rxe','shp','shpgrp','shpinst', 
     'shppict','shprslt','shptxt','sn','sp','staticval','stylesheet','subject','sv', 
     'svb','tc','template','themedata','title','txe','ud','upr','userprops', 
     'wgrffmtfilter','windowcaption','writereservation','writereservhash','xe','xform', 
     'xmlattrname','xmlattrvalue','xmlclose','xmlname','xmlnstbl', 
     'xmlopen', 
    )) 
    # Translation of some special characters. 
    specialchars = { 
     'par': '\n', 
     'sect': '\n\n', 
     'page': '\n\n', 
     'line': '\n', 
     'tab': '\t', 
     'emdash': u'\u2014', 
     'endash': u'\u2013', 
     'emspace': u'\u2003', 
     'enspace': u'\u2002', 
     'qmspace': u'\u2005', 
     'bullet': u'\u2022', 
     'lquote': u'\u2018', 
     'rquote': u'\u2019', 
     'ldblquote': u'\201C', 
     'rdblquote': u'\u201D', 
    } 
    stack = [] 
    ignorable = False  # Whether this group (and all inside it) are "ignorable". 
    ucskip = 1    # Number of ASCII characters to skip after a unicode character. 
    curskip = 0    # Number of ASCII characters left to skip 
    out = []    # Output buffer. 
    for match in pattern.finditer(text): 
     word,arg,hex,char,brace,tchar = match.groups() 
     if brace: 
     curskip = 0 
     if brace == '{': 
      # Push state 
      stack.append((ucskip,ignorable)) 
     elif brace == '}': 
      # Pop state 
      ucskip,ignorable = stack.pop() 
     elif char: # \x (not a letter) 
     curskip = 0 
     if char == '~': 
      if not ignorable: 
       out.append(u'\xA0') 
     elif char in '{}\\': 
      if not ignorable: 
       out.append(char) 
     elif char == '*': 
      ignorable = True 
     elif word: # \foo 
     curskip = 0 
     if word in destinations: 
      ignorable = True 
     elif ignorable: 
      pass 
     elif word in specialchars: 
      out.append(specialchars[word]) 
     elif word == 'uc': 
      ucskip = int(arg) 
     elif word == 'u': 
      c = int(arg) 
      if c < 0: c += 0x10000 
      if c > 127: out.append(unichr(c)) 
      else: out.append(chr(c)) 
      curskip = ucskip 
     elif hex: # \'xx 
     if curskip > 0: 
      curskip -= 1 
     elif not ignorable: 
      c = int(hex,16) 
      if c > 127: out.append(unichr(c)) 
      else: out.append(chr(c)) 
     elif tchar: 
     if curskip > 0: 
      curskip -= 1 
     elif not ignorable: 
      out.append(tchar) 
    return ''.join(out) 

它的工作原理解析RTF代码,并跳过其中有一个“目的地”的任何组指定的,和所有的“可忽略“组({\* ... })。我还添加了一些特殊字符的处理。

有很多功能缺少使这个完整的解析器,但应该足够简单的文件。

更新:这个网址有此脚本更新到Python的3.x运行:

https://gist.github.com/gilsondev/7c1d2d753ddb522e7bc22511cfb08676

+0

不错的答案。 \〜是非破坏性的空间,所以不应该char =='〜'追加u'\ u00a0? – 2011-12-24 23:53:45

+0

确实。更新。谢谢。 – 2011-12-25 10:49:31

1

没有一个答案是足够的,所以我的解决方案是使用RichTextBox控件(是的,即使在非WinForm的应用程序)从RTF

提取文本
1
  FareRule = Encoding.ASCII.GetString(FareRuleInfoRS.Data); 
       System.Windows.Forms.RichTextBox rtf = new System.Windows.Forms.RichTextBox(); 
       rtf.Rtf = FareRule; 
       FareRule = rtf.Text; 
6

到目前为止,我们还没有找到一个很好的答案,这无论是,除了使用RichTextBox控件:

/// <summary> 
    /// Strip RichTextFormat from the string 
    /// </summary> 
    /// <param name="rtfString">The string to strip RTF from</param> 
    /// <returns>The string without RTF</returns> 
    public static string StripRTF(string rtfString) 
    { 
     string result = rtfString; 

     try 
     { 
      if (IsRichText(rtfString)) 
      { 
       // Put body into a RichTextBox so we can strip RTF 
       using (System.Windows.Forms.RichTextBox rtfTemp = new System.Windows.Forms.RichTextBox()) 
       { 
        rtfTemp.Rtf = rtfString; 
        result = rtfTemp.Text; 
       } 
      } 
      else 
      { 
       result = rtfString; 
      } 
     } 
     catch 
     { 
      throw; 
     } 

     return result; 
    } 

    /// <summary> 
    /// Checks testString for RichTextFormat 
    /// </summary> 
    /// <param name="testString">The string to check</param> 
    /// <returns>True if testString is in RichTextFormat</returns> 
    public static bool IsRichText(string testString) 
    { 
     if ((testString != null) && 
      (testString.Trim().StartsWith("{\\rtf"))) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

编辑:添加了IsRichText方法。

4

它看起来像使用Richtextbox是微软的这个问题的正式答案!

3

我做了这个辅助函数在JavaScript中做到这一点。到目前为止,这对于我简单的RTF格式删除非常有效。

function stripRtf(str){ 
    var basicRtfPattern = /\{\*?\\[^{}]+;}|[{}]|\\[A-Za-z]+\n?(?:-?\d+)?[ ]?/g; 
    var newLineSlashesPattern = /\\\n/g; 
    var ctrlCharPattern = /\n\\f[0-9]\s/g; 

    //Remove RTF Formatting, replace RTF new lines with real line breaks, and remove whitespace 
    return str 
     .replace(ctrlCharPattern, "") 
     .replace(basicRtfPattern, "") 
     .replace(newLineSlashesPattern, "\n") 
     .trim(); 
} 

注:

  • 我稍微修改由@Markus Jarderot上面写的正则表达式。它现在在两个步骤中以新行结尾删除斜杠以避免更复杂的正则表达式。
  • .trim()仅在较新的浏览器中受支持。如果您需要对这些支持,然后看到:Trim string in JavaScript?

编辑:我已经更新了正则表达式来解决一些问题,因为最初发布这个我已经找到。我在一个项目中使用它,在这里看到它:https://github.com/chrismbarr/LyricConverter/blob/865f17613ee8f43fbeedeba900009051c0aa2826/scripts/parser.js#L26-L37

2

后期贡献者,但下面的正则表达式帮助我们在我们的数据库中找到的RTF代码(我们通过SSRS在RDL中使用它)。

此表达式已将其删除,供我们的团队使用。虽然它可能只是解决我们特定的RTF,但它可能对某人有用。虽然这个webby是现场测试非常方便。

http://regexpal.com/

{\*?\\.+(;})|\s?\\[A-Za-z0-9]+|\s?{\s?\\[A-Za-z0-9]+\s?|\s?}\s? 

希望这有助于 ķ

0

下面是一个Oracle SQL语句,可以从Oracle场脱衣RTF:

SELECT REGEXP_REPLACE(
    REGEXP_REPLACE(
     CONTENT, 
     '\\(fcharset|colortbl)[^;]+;', '' 
    ), 
    '(\\[^ ]+ ?)|[{}]', '' 
) TEXT 
FROM EXAMPLE WHERE CONTENT LIKE '{\rtf%'; 

这是专为从Windows数据丰富的文本控件,而不是RTF文件。 限制是:

  • \{\}不与{}
  • 头更换和页脚没有特殊处理
  • 图像和其他嵌入对象不是特殊处理(不知道会发生什么,如果一个)

它通过首先删除\fcharset\colourtbl标签,它们是因为数据紧随其后直到达到;。然后删除所有\xxx标签(包括一个可选的尾部空格),然后删除所有{}字符。这可以处理最简单的RTF,例如从富文本控件获得的内容。

相关问题