2

注: stringByReplaceingOccurrencesOfString を何度も何度も使用したくないと明確に述べたので、これが重複としてマークされている理由がわかりません。

特殊文字のファイル名について質問があります。

ファイルまたは複数のファイルを開くと、プログラムがこれらすべてのファイル名とローカル パスを読み取り、それらを 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

ファイルを適切に操作できるようにします。

(とについても同じです)。その前にバックスラッシュも追加する必要があります。

しかし、特殊文字が多すぎます。すなわち。

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

次のように変更する必要があります。

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

他の特殊文字(つまりアクセント)は言うまでもありません

stringByReplacingOccurrencesOfString何度も何度も呼び出し続けたくないので、各特殊文字の前にバックスラッシュを置く簡単な方法はありますか?

4

3 に答える 3

1

NSTaskメソッドに関する のドキュメントで説明されているsetArguments:ように、特別な引用を行う必要はありません。

討論

NSTaskオブジェクトは、パス引数の文字列の両方を適切な C スタイルの文字列に (fileSystemRepresentation を使用して) 変換してから、 を介してタスクに渡しますargv[]引数の文字列はシェル展開されないため、特別な引用符を付ける必要はなく、 などのシェル変数$PWDは解決されません。

必要だと思われる場合は、で実行したいコマンドの例をいくつか教えてくださいNSTask

[UPDATE]: 私が疑問に思っていた でシェルNSTaskを実行するために実際に を使用していることをコメントで確認しました。私は通常、次のように、シェルを経由するのではなく、コマンドを直接実行していました。bash-cNSTask

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 に答える
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 に答える
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 に答える