Регулярное выражение для извлечения текста от строки RTF

Указатель NULL - это тот, который указывает на никуда. Когда вы разыскиваете указатель p, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p является нулевым указателем, местоположение, хранящееся в p, является nowhere, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception.

В общем, это потому, что что-то не было правильно инициализировано.

38
задан Markus Jarderot 8 July 2010 в 07:57
поделиться

6 ответов

В RTF {и} метках группа. Группы могут быть вложены. \начало меток управляющего слова. Управляющие слова заканчиваются или пространством или не буквенным символом. Управляющее слово может иметь числовой параметр после без любого промежуточного разделителя. Некоторые управляющие слова также берут текстовые параметры, разделенные'';. те управляющие слова обычно находятся в их собственных группах.

я думаю, что мне удалось сделать шаблон, который заботится о большинстве случаи.

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

Это оставляет несколько пробелов, когда работается Вашим шаблоном все же.

<час>

Идущая канавка спецификация RTF (часть его), я вижу, что существует много ловушек для базирующихся стрипперов чистого regex. Самый очевидный - то, что некоторые группы должны быть проигнорированы (заголовки, нижние колонтитулы, и т.д.), в то время как другие должны быть представлены (форматируя).

я записал сценарий Python, который должен работать лучше, чем мой regex выше:

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 и пропуска любых групп, который имеет "место назначения", определенное, и все "игнорируемые" группы ({\*... }). Я также добавил обработку некоторых специальных символов.

существует много функций, отсутствующих для создания этого полным синтаксическим анализатором, но должно быть достаточно для простых документов.

ОБНОВЛЕННЫЙ: Этот URL обновили этот сценарий для работы Python 3.x:

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

56
ответ дан Gilson Filho 27 November 2019 в 03:25
поделиться

Я использовал это прежде, и это работало на меня:

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

Вы, вероятно, захотите обрезать концы результата избавиться от перенесенных дополнительных пространств.

6
ответ дан John Chuckran 27 November 2019 в 03:25
поделиться

Согласно RegexPal, два}'s - те полужирные ниже:

{\\rtf1\ansi\ansicpg1252\deff0\deflang1033 {\\fonttbl {\\f0\fnil\fcharset0 MS Shell Dlg 2;} {\\f1\fnil MS Shell Dlg 2;} } {\\colortbl; \red0\green0\blue0;} {\\генератор Msftedit 5.41.15.1507; }\\viewkind4\uc1\pard\tx720\cf1\f0\fs20 может Вы отправлять мне информацию за please\f1\par вызова}

, я смог зафиксировать первую изогнутую фигурную скобку путем добавления знака "плюс" к regex:

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

И зафиксировать изогнутую фигурную скобку в конце, я сделал это:

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

я не знаю RTF-формат очень хорошо, таким образом, это не могло бы работать во всех случаях, но он работает над Вашим примером...

2
ответ дан Jeremy Ruten 27 November 2019 в 03:25
поделиться

Ни одного из ответов не было достаточно, поэтому я решил использовать элемент управления RichTextBox (да, даже в приложении, отличном от Winform), чтобы извлечь текст из RTF

1
ответ дан 27 November 2019 в 03:25
поделиться

Следующее решение позволяет извлекать текст из строки RTF:

FareRule = Encoding.ASCII.GetString(FareRuleInfoRS.Data);
    System.Windows.Forms.RichTextBox rtf = new System.Windows.Forms.RichTextBox();
    rtf.Rtf = FareRule;
    FareRule = rtf.Text;
1
ответ дан 27 November 2019 в 03:25
поделиться

До сих пор мы не нашли хорошего ответа и на этот вопрос, кроме использования элемента управления 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.

7
ответ дан 27 November 2019 в 03:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: