【问题标题】:NSRegularExpression separating paragraphsNSRegularExpression 分隔段落
【发布时间】:2023-03-30 02:08:01
【问题描述】:

考虑一下这段文字:

Paragraph 1: Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat. 

Paragraph 2 Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat.







Paragraph 3 Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat.

在ObjC中,阅读上述文字时,paragraph1和paragraph2之间有两个\n\n行空格。但是在第 2 段和第 3 段之间有超过 3 个行空格\n\n\n\n

我想要一个 NSRegularExpression 模式,它可以读取并返回这些段落,完全不考虑行空间的数量。

NSString *pattern = @"\n(*\n)\n";

NSRegularExpression* regex1 = [[NSRegularExpression alloc] initWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];

NSArray *array = [regex1 matchesInString:p options:0 range:NSMakeRange(0, [p length])];
for(NSTextCheckingResult *tcr in array){
    NSTextCheckingResult *tcr = [regex1 firstMatchInString:p options:0 range:NSMakeRange(0, p.length)];
    NSRange matchRange = [tcr rangeAtIndex:1];
    NSString *amatch = [p substringWithRange:matchRange];
    NSLog(@"Found string: %@", amatch);
}

我是 NSRegularExpression 的新手,任何对更好教程的参考都会很棒。在这种情况下,这是解决上述问题的正确方法吗?

【问题讨论】:

  • 这根本不需要 NSRegularExpression。 NSString 中内置了很多自然语言解析函数。例如,您可以逐段枚举字符串。请参阅下面的答案。

标签: ios objective-c regex nsregularexpression


【解决方案1】:

您不需要 NSRegularExpression 来执行此操作。 NSString 内置了大量非常有用的自然语言解析函数。

最好的方法是像这样枚举字符串...

NSString *string = @"Paragraph 1: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n\n\nParagraph 2 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n\n\n\n\n\n\n\n\n\nParagraph 3 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";

NSMutableArray *paragraphs = [NSMutableArray array];

[string enumerateSubstringsInRange:NSMakeRange(0, string.length) 
                           options:NSStringEnumerationByParagraphs 
                        usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
    [paragraphs addObject:substring];
}];

for (NSString *paragraph in paragraphs) {
    NSLog(@"%@", paragraph);
}

这会将每个段落放入 NSMutableArray 段落中。

这不需要任何解析或正则表达式等...它也可能比你可以编写的任何东西都快,因为它是一个原生函数。

【讨论】:

  • 我假设输入字符串可以在段落中包含换行符,并且他通过使用两个连续的换行符来区分段落。但你说的很对,如果段落由单个换行符分隔,那么这种技术很棒。
【解决方案2】:

我相信使用标准的 NSString 方法可能会更容易完成:

NSArray *allParagraphs = [text componentsSeparatedByString:@"\n\n"];

NSCharacterSet *charactersToTrim = [NSCharacterSet whitespaceAndNewlineCharacterSet];
for (NSString *paragraph in allParagraphs) {
    NSString *trimmedParagraph = 
            [paragraph stringByTrimmingCharactersInSet:charactersToTrim];
}

或者,如果您想使用正则表达式,请尝试以下操作:

"(.*?)(\\n{2,}|$)"

它保留所有符号,直到找到两个或更多新行或文件结尾

编辑。

NSRegularExpression *regexp =
        [NSRegularExpression regularExpressionWithPattern:@"(.*?)(\\n{2,}|$)"
                                                  options:NSRegularExpressionDotMatchesLineSeparators
                                                    error:nil];
[regexp enumerateMatchesInString:TEST_STRING
                         options:0
                           range:NSMakeRange(0, TEST_STRING.length)
                      usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop){
                          NSLog(@"%@", [TEST_STRING substringWithRange:[result rangeAtIndex:1]]);
                      }];

【讨论】:

  • 嘿,感谢您的回复,是的,NSCharacterSet 会这样做,但我正在寻找正则表达式解决方案。 "(.*?)(\\n{2,}|$)" 确实有效,除了第一段,它在被跳过之前没有 \n。对此有何修改? `
  • 我检查了这个解决方案,它适用于所有段落 - 它在段落之后检查新行(或文件结尾 - $ 符号)。您还应该添加选项 NSRegularExpressionDotMatchesLineSeparators
【解决方案3】:

下面的工作。我还使用enumerateMatchesInString 来查找匹配项。

NSString *pattern = @"(\\A|\\n\\s*\\n)(.*?\\S[\\s\\S]*?\\S)(?=(\\Z|\\s*\\n\\s*\\n))";
NSRegularExpression* regex = [[NSRegularExpression alloc] initWithPattern:pattern
                                                                  options:NSRegularExpressionCaseInsensitive
                                                                    error:&error];

[regex enumerateMatchesInString:input
                        options:0
                          range:NSMakeRange(0, [input length])
                     usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
                         NSString *match = [input substringWithRange:[result rangeAtIndex:2]];
                         NSLog(@"match = '%@'", match);
                     }];

这不仅返回两个换行符之间的字符串(忽略返回之间的任何额外空格),还返回第一个(即字符串的开头和两个换行符的第一个序列之间)和最后一个(即在两个换行符的最后一个序列和字符串的结尾之间。

【讨论】:

  • 嘿,这行得通,但是有一个问题,如果段落中只有一行,则无法将其捕获为一行,并继续添加下一个 文本在任何 newline 间隔之后的行。
  • 刚刚再次注意到,当一个段落至少有两行时它可以工作。带有单个长文本的段落,例如问题中的示例文本,它失败了。
  • @jasonIM 在".*" 之后插入"?",例如@"(\\A|\\n\\s*\\n)(.*?\\S[\\s\\S]*?\\S)(?=(\\Z|\\s*\\n\\s*\\n))"
  • 你太棒了,就像一个魅力,这对我理解正则表达式有很大帮助!
【解决方案4】:

我无法帮助您进行 NSRegularExpression 匹配和替换,但我相信您正在寻找的正则表达式是 \\n(\\n)+

您需要对换行符进行两次转义。一次用于 C 字符串,一次用于正则表达式。 + 字符表示上一组中的一个或多个。

【讨论】:

  • 嘿,谢谢你的回复,我无法让它工作,但我确实让[^\n]+ 返回每​​一行(直到字符返回),但我想要每个文本之间的 两个或多个 换行符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多