Лучший способ избежать символов, таких как newline и double-quote в NSString

Скажем, у меня есть NSString (или NSMutableString), содержащий:

I said "Hello, world!".
He said "My name not World."

Какой лучший способ превратить это в:

I said \"Hello, world!\".\nHe said \"My name\ not World.\"

Должен ли я вручную использовать -replaceOccurrencesOfString:withString: снова и снова для удаления символов, или есть более простой способ? Эти строки могут содержать символы из других алфавитов/языков.

Как это делается на других языках с другими строковыми классами?

Ответ 1

Я не думаю, что есть встроенный способ "избежать" определенного набора символов.

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

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

Если вам нужно поддерживать переменный набор экранированных символов, взгляните на методы NSScanner "scanUpToCharactersFromSet: inString:" и "scanCharactersFromSet: inString:". Вы можете использовать эти методы в NSScanner для перемещения по строке, копируя части из раздела "scanUpTo" в изменяемую строку без изменений и копируя детали из определенного набора символов только после их выхода.

Ответ 2

stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding

Ответ 3

Это приведет к двойным кавычкам в NSString:

NSString *escaped = [originalString stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];

Итак, вам нужно быть осторожным, а также избежать escape-символа...

Ответ 4

Я думаю, что в подобных случаях полезно работать с символом за раз, либо в байтах UniChars, либо в UTF8. Если вы используете UTF-8, то vis(3) выполнит большую часть работы для вас (см. Ниже). Могу ли я спросить, почему вы хотите избежать одиночной кавычки в строке с двумя кавычками? Как вы планируете обрабатывать многобайтовые символы? В приведенном ниже примере я использую UTF-8, кодируя 8-битные символы, используя восьмеричные escape-последовательности C-Style. Это также можно отменить unvis(3).

#import <Foundation/Foundation.h>
#import <vis.h>

@interface NSString (Escaping)

- (NSString *)stringByEscapingMetacharacters;

@end

@implementation NSString (Escaping)

- (NSString *)stringByEscapingMetacharacters
{
    const char *UTF8Input = [self UTF8String];
    char *UTF8Output = [[NSMutableData dataWithLength:strlen(UTF8Input) * 4 + 1 /* Worst case */] mutableBytes];
    char ch, *och = UTF8Output;

    while ((ch = *UTF8Input++))
        if (ch == '\'' || ch == '\'' || ch == '\\' || ch == '"')
        {
            *och++ = '\\';
            *och++ = ch;
        }
        else if (isascii(ch))
            och = vis(och, ch, VIS_NL | VIS_TAB | VIS_CSTYLE, *UTF8Input);
        else
            och+= sprintf(och, "\\%03hho", ch);

    return [NSString stringWithUTF8String:UTF8Output];
}

@end

int
main(int argc, const char *argv[])
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    NSLog(@"%@", [@"I said \"Hello, world!\".\nHe said \"My name not World.\"" stringByEscapingMetacharacters]);

    [pool drain];
    return 0;
}

Ответ 5

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

- (NSString *)escapeString:(NSString *)aString
{
    NSMutableString *returnString = [[NSMutableString alloc] init];

    for(int i = 0; i < [aString length]; i++) {

        unichar c = [aString characterAtIndex:i];

        // if char needs to be escaped
        if((('\\' == c) || ('\'' == c)) || ('"' == c)) {
            [returnString appendFormat:@"\\%c", c];            
        } else {
            [returnString appendFormat:@"%c", c];
        }
    }

    return [returnString autorelease];   
}

Ответ 7

Возможно, вы даже захотите изучить библиотеку регулярных выражений (имеется много доступных опций, RegexKit - популярный выбор). Не должно быть слишком сложно найти предварительно написанное регулярное выражение, чтобы избежать строк, которые обрабатывают специальные случаи, такие как существующие экранированные символы.