2008-10-09 75 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,例如從富文本控件獲得的內容。

相關問題