2

注意:不知道为什么这被标记为重复,因为我明确表示我不想一遍又一遍地使用 stringByReplacingOccurrencesOfString。

我对特殊字符文件名有疑问。

我已经实现了一个程序,这样当你打开一个或多个文件时,程序会读取所有这些文件名和本地路径并将它们存储到 NSMutableArray 中。这部分工作完美,没有问题。

我的程序还需要使用 NSTask 来操作这些文件。但是,问题是,有时文件名会包含特殊字符,例如 /Users/josh/Desktop/Screen Shot 2013-03-19 at 2.05.06 PM.png.

我必须用反斜杠和空格替换空格

NSString *urlPath = [[self url] path];
urlPath = [urlPath stringByReplacingOccurrencesOfString:@"(" withString:@"\\("];
urlPath = [urlPath stringByReplacingOccurrencesOfString:@")" withString:@"\\)"];
urlPath = [urlPath stringByReplacingOccurrencesOfString:@" " withString:@"\\ "];

到:/Users/josh/Desktop/Screen\ Shot\ 2013-03-19\ at\ 2.05.06\ PM.png

这样我就可以正确操作文件。

(和相同)。在此之前我还需要添加反斜杠。

但是特殊字符太多了。IE。

/Users/josh/Desktop/~!@#$?:<,.>%^&*()_+`-={}[]\|'';.txt

我需要更改为:

/Users/josh/Desktop/\~\!@\#\$\?\:\<\,.\>\%^\&\*\(\)_+\`-\=\{\}\[\]\\\|\'\'\;.txt

更不用说其他特殊字符(即重音)

有什么简单的方法可以在每个特殊字符前面加上反斜杠,因为我不想stringByReplacingOccurrencesOfString一遍又一遍地打电话。

4

3 回答 3

1

我想你也许可以使用NSRegularExpressionSearch搜索。

它看起来像这样

+ (NSString *) addBackslashes: (NSString *) string
{
    // First convert the name string to a pure ASCII string
    NSData *asciiData = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

    NSString *asciiString = [[[NSString alloc] initWithData:asciiData encoding:NSASCIIStringEncoding] lowercaseString];

    // Define the characters that we will replace
    NSString *searchCharacters = @"PUT IN ALL OF YOUR SPECIAL CHARACTERS HERE";
    // example NSString *searchCharacters = @"!@#$%&*()";

    // replace them
    NSString *regExPattern = [NSString stringWithFormat:@"[%@]", searchCharacters];

    string = [asciiString stringByReplacingOccurrencesOfString:regExPattern withString: [NSString stringWithFormat:@"\\%@", regExPattern] options:NSRegularExpressionSearch range:NSMakeRange(0, asciiString.length)];
    return string;
}
于 2013-03-19T20:56:37.733 回答
1

NSTask该方法的文档中所述setArguments:,不需要进行特殊引用:

讨论

NSTask对象在将路径参数中的字符串通过argv[]. 参数中的字符串不进行 shell 扩展,因此您不需要做特殊的引用,并且 shell 变量,例如$PWD,不会被解析。

如果您觉得有必要,您能否提供一些您想在 ? 中运行的命令的示例NSTask

[更新]:我在评论中看到您确实在使用NSTask来执行bashshell -c,这是我想知道的。我通常习惯于NSTask直接执行命令,而不是通过 shell,如下所示:

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/ls"];
[task setArguments:[NSArray arrayWithObjects:@"-l", self.url.path, nil]];

你能给出一个更准确的例子来说明你想要运行的实际命令吗?例如,您是否将一系列命令连接在一起?也许可能有另一种方法可以在不需要使用bash外壳的情况下实现相同的结果......

于 2013-03-19T21:05:57.160 回答
0

您可以维护一组需要转义的字符串,并使用 NSScanner 通过迭代源字符串来构建新字符串,每次发现有问题的字符时,您首先添加\\到目标字符串并继续处理下一个字符。

NSString *sourceString = @"/Users/josh/Desktop/\"Screen Shot\" 2013-03-19 at 2\\05\\06 PM.png";
NSMutableString *destString = [@"" mutableCopy];
NSCharacterSet *escapeCharsSet = [NSCharacterSet characterSetWithCharactersInString:@" ()\\"];

NSScanner *scanner = [NSScanner scannerWithString:sourceString];
while (![scanner isAtEnd]) {
    NSString *tempString;
    [scanner scanUpToCharactersFromSet:escapeCharsSet intoString:&tempString];
    if([scanner isAtEnd]){
        [destString appendString:tempString];
    }
    else {
        [destString appendFormat:@"%@\\%@", tempString, [sourceString substringWithRange:NSMakeRange([scanner scanLocation], 1)]];
        [scanner setScanLocation:[scanner scanLocation]+1];
    }
}

NSLog(@"\n%@\n%@", sourceString, destString);

结果:

/Users/josh/Desktop/Screen Shot 2013-03-19 at 2.05.06 PM.png
/Users/josh/Desktop/Screen\ Shot\ 2013-03-19\ at\ 2.05.06\ PM.png
于 2013-03-19T20:58:19.787 回答