2014-12-15 2 views
1

У меня проблема, когда я хочу разбор некоторых Markdown, и когда я пытаюсь разобрать текст с акцентом, где подчеркивается текст, заключенный в подчеркивания (например, this is some _emphasized_ text).Как использовать NSRegularExpression, где, если раздел обнаружен и заменен, он не будет сделан снова?

Однако ссылки также имеют в них символы подчеркивания, такие как http://example.com/text_with_underscores/, и в настоящее время мое регулярное выражение подхватит _with_ как попытку подчеркнуть текст.

Очевидно, что я не хочу этого, и поскольку текст с акцентом в середине этого действителен (например, longword*with*emphasis является действительным), мое решение состоит в том, чтобы сначала разобрать ссылки и почти «отметить» эти замены чтобы его не трогали снова. Это возможно?

+0

Итак, вы хотите заменить _ на * ?? –

+0

@ HussainShabbir HTML, в данном случае. Так '_word_' становится' слово '. –

+0

Итак, вы хотите, чтобы это было -with- становится с правом ?? –

ответ

0

Одно из решений можно реализовать так: -

NSString *[email protected]"this is some _emphasized_ text"; 
NSMutableString *mutStr=[NSMutableString string]; 
NSUInteger count=0; 
for (NSUInteger i=0; i<yourStr.length; i++) 
{ 
    unichar c =[yourStr characterAtIndex:i]; 
    if ((c=='_') && (count==0)) 
    { 
    [mutStr appendString:[NSString stringWithFormat:@"%@",@"<em>"]]; 
     count++; 
    } 
    else if ((c=='_') && (count>0)) 
    { 
     [mutStr appendString:[NSString stringWithFormat:@"%@",@"</em>"]]; 
     count=0; 
    } 
    else 
    { 
     [mutStr appendString:[NSString stringWithFormat:@"%C",c]]; 
    } 

} 
NSLog(@"%@",mutStr); 

Выход: -

this is some <em>emphasized</em> text 
+0

Подождите, этот вывод не имеет смысла. Как я уже сказал в исходном сообщении, он не должен делать это для URL-адресов, но он должен использоваться для не-URL-адресов. Я бы хотел, чтобы URL-адрес анализировался как один без добавления случайного акцента, и подчеркивал текст, который нужно подчеркнуть. –

0
__block NSString *yourString = @"media_w940996738_ _help_ 476.mp3"; 
NSError *error = NULL; 
__block NSString *yourNewString; 
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"([_])\\w+([_])" options:NSRegularExpressionCaseInsensitive error:&error]; 

    yourNewString=[NSString stringWithString:yourString]; 
[regex enumerateMatchesInString:yourString options:0 range:NSMakeRange(0, [yourString length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){ 

    // detect 

    NSString *subString = [yourString substringWithRange:[match rangeAtIndex:0]]; 
    NSRange range=[match rangeAtIndex:0]; 
    range.location+=1; 
    range.length-=2; 
    //print 
    NSString *string=[NSString stringWithFormat:@"<em>%@</em>",[yourString substringWithRange:range] ]; 
    yourNewString = [yourNewString stringByReplacingOccurrencesOfString:subString withString:string]; 


}]; 
+0

Как это * не * соответствует _ в URL-адресах? – CRD

+0

Вы можете использовать свой url как строку –

0

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

Рассмотрим:

  1. matchesInString:options:range возвращает все неперекрывающиеся совпадения для регулярного выражения.

  2. Регулярные выражения построены из меньших регулярных выражений и могут содержать альтернативы. Так что если у вас есть переакцентировку, которая соответствует последовательности, чтобы подчеркнуть и REurl, который соответствует URL, затем (переакцентировку) | (REurl) соответствует обоим.

  3. NSTextCheckingResult, экземпляры которых возвращается matchesInString:options:range, сообщает диапазон каждой группы в матче, и если группа не возникает в результате из-за альтернативы в схеме, то группа-х NSRange.location установлена ​​в NSNotFound. Таким образом, для приведенного выше рисунка, (переакцентировку) | (REurl), если группа 1 является NSNotFound матч является для REurl альтернатива в противном случае для переакцентировку альтернативы.

  4. Метод replacementStringForResult:inString:offset:template возвращает строку замены для соответствия на основе шаблона (aka).

Вышесказанное достаточно, чтобы написать алгоритм, чтобы делать то, что вы хотите.Вот некоторые примеры кода:

- (NSString *) convert:(NSString *)input 
{ 
    NSString *emphPat = @"(_([^_]+)_)"; // note this pattern does NOT allow for markdown's \_ escapes - that needs to be addressed 
    NSString *emphRepl = @"<em>$2</em>"; 

    // a pattern for urls - use whatever suits 
    // this one is taken from http://stackoverflow.com/questions/6137865/iphone-reg-exp-for-url-validity 
    NSString *urlPat = @"([hH][tT][tT][pP][sS]?:\\/\\/[^ ,'\">\\]\\)]*[^\\. ,'\">\\]\\)])"; 

    // construct a pattern which matches emphPat OR urlPat 
    // emphPat is first so its two groups are numbered 1 & 2 in the resulting match 
    NSString *comboPat = [NSString stringWithFormat:@"%@|%@", emphPat, urlPat]; 

    // build the re 
    NSError *error = nil; 
    NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:comboPat options:0 error:&error]; 
    // check for error - omitted 

    // get all the matches - includes both urls and text to be emphasised 
    NSArray *matches = [re matchesInString:input options:0 range:NSMakeRange(0, input.length)]; 

    NSInteger offset = 0;      // will track the change in size 
    NSMutableString *output = input.mutableCopy; // mutuable copy of input to modify to produce output 

    for (NSTextCheckingResult *aMatch in matches) 
    { 
     NSRange first = [aMatch rangeAtIndex:1]; 

     if (first.location != NSNotFound) 
     { 
     // the first group has been matched => that is the emphPat (which contains the first two groups) 

     // determine the replacement string 
     NSString *replacement = [re replacementStringForResult:aMatch inString:output offset:offset template:emphRepl]; 

     NSRange whole = aMatch.range;    // original range of the match 
     whole.location += offset;     // add in the offset to allow for previous replacements 
     offset += replacement.length - whole.length; // modify the offset to allow for the length change caused by this replacement 

     // perform the replacement 
     [output replaceCharactersInRange:whole withString:replacement]; 
     } 
    } 

    return output; 
} 

Примечание выше не позволяет \ _ последовательности побега Markdown и вам нужно решить эту проблему. Вероятно, вам также необходимо рассмотреть RE, используемую для URL-адресов - один был вырван из SO и не был протестирован должным образом.

выше будет конвертировать

http://example.com/text_with_underscores _emph_

в

http://example.com/text_with_underscores < эм > EMPH </эм >

HTH