一半君的总结纸

听话只听一半君

#34 如何保证Windows的文件路径是反斜杠\ (而Maya中用到的路径用的是/)?

方法 #1: 使用 “fromNativePath” 和 “toNativePath

注意: 这些只有在windows下用的必要(因为linux和Maya一样是用 / 的).

toNativePath” command 能把一个使用 / 的 (或者是 / 和 \ 混用的 ) 路径转换成全部使用 \ 的.

string $path = "C:/path/file.mel";
// Result: C:/path/file.mel //

toNativePath( $path );
// Result: C:\path\file.mel //

string $path = "C:\\path/file.mel";
// Result: C:\path/file.mel //

toNativePath( $path );
// Result: C:\path\file.mel //

fromNativePath” 能把一个使用 \ 的 (或者是 \ 和 / 混用的 )路径转换成全部使用 / 的.

string $path = "C:\\path\\file.mel";
// Result: C:\path\file.mel //

fromNativePath( $path );
// Result: C:/path/file.mel //

string $path = "C:\\path/file.mel";
// Result: C:\path/file.mel //

fromNativePath( $path );
// Result: C:/path/file.mel //

方法 #2: 使用 “substitute” command

当使用 “substitute” command的时候有几件事要小心.

首先, “substitute” 只执行 一次 替换. 他不会替换所有匹配的字符串. 如果你想替换全部,你就得把他放在一个 while() 循环里.

  string $path = "C:/path/file.mel";
  while ( $path != ( $path = `substitute "/" $path "\\"` ) );
  // Result: C:\path\file.mel //

虽然从 / 换成 \ 非常简单, 但是从 \ 换成 / 就要麻烦一点了. 因为 substitute command 的第一个参数可以是正则表达式,所以你必须把匹配字符串里的所有\ 都写成 \\ , 换句话说, 如果你想替换所有的”\” 字符,你的source characer就必须是 “\\\\” . 每个”\\” 对首先被 expression parser 转义解读一遍, 此时 “\\\\” 被转换成了 “\\“, 然后 then 这个字符串继续被传递给 ‘substitute’ command,结果导致他再次被转义解读一遍,最终变成了单个的 \ . 上述的过程仅会发生在替换的 source string 的身上,; destination string 只需要转义解读一次. 我知道这设计的有点奇怪.

// Maya 不认这种写法.
while ( $path != ( $path = `substitute "\\" $path "/"` ) );

如果这样写会出现如下错误提示:

// Error: line 1: Invalid escape sequence: Missing character after last backslash "\" in string "\". //

(如果你的Maya版本小于v2.5, Maya 会跳出)

// substitute的第一个参数的每个 \ 都必须是 \\.
string $path = "C:\\path\\file.mel";
while ( $path != ( $path = `substitute "\\\\" $path "/"` ) );
// Result: C:/path/file.mel //

此外, 如果你想把 \ 换成 \\ (比如在拼凑给 callback argument用的字符串的时候) 你必须首先把这个字符换成一个占位符(placeholder), 然后再把所有的 placeholders 换成 \\ . 否则 while() loop 会变成无限循环, 每次都会找到更多需要替换的 \.

// 首先把所有的 \\\\ 换成 *.
while ( $path != ( $path = `substitute "\\\\" $path "*"` ) );
// Result: C:*path*file.mel //

// 现在把所有的 * 换成 \.
// 注意: * 在这里必须被转义 也就是说必须用\*.
while ( $path != ( $path = `substitute "\\*" $path "\\\\"` ) );
// Result: C:\\path\\file.mel //

注意 “\\*” argument 被转义了两次, 就和上面提到的想替换 \ 的时候一样. 第二个 “\\\\” argument 和你想指定 \\ 的时候一样 – 每个 \ 只被转义了一次.

方法 #3: 使用 ‘tokenize’ command

此方法比上面两种更灵活,因为你可以自己决定怎么得到路径; 比如你可以自行决定路径结尾是不是有 / 或者他是相对路径还是绝对路径.

下面是一个我用来把路径转换成windows用的/的小工具proc.

proc string slash( string $path )
// 输入: 以 '/' 或 '\' 分隔的路径.
// 输出: 以 '\' 分隔的路径.
{
  string $slash = "";

  string $tokens[];
  int $numTokens = `tokenize $path "\\/" $tokens`;
  int $i;

  $slash = $tokens[0];

  for ( $i = 1; $i < $numTokens; $i++ )
  {
    $slash += ( "\\" + $tokens[$i] );
  }

  return $slash;
}

使用举例:

  string $path = "C:/path/file.mel";
  $path = slash($path);
  // Result: C:\path\file.mel //

其他例子:(连接已挂)

slash2.mel

slash.mel 一样,可以指定一个额外 ‘$isDir’ parameter , 如果路径末尾还有一个多余的 / 或者 \ 并且给出的路径是个目录的话.

doubleslash.mel

把所有的 “\” 替换成 “\\” ,然后得到的结果文件路径字符串就可以在 ‘eval’ statement, expression, 或者其他地方使用了.

加强版:

python时代已经完全不用这样了
方法 #3的tokenize已经完全可以用

filename='C:/path/file.mel'
filename.replace('/','\\')
# Result: 'C:\\path\\file.mel' #

来代替

离题一下,如果仅仅考虑tokenize的话,而且有多个可能的分隔符的时候,也许你/ \都有或是有更多的其他分隔符,在python时代应该这么用

import re
re.split('; |, ',str)

>>> a='Beautiful, is; better*than\nugly'
>>> import re
>>> re.split('; |, |\*|\n',a)
['Beautiful', 'is', 'better', 'than', 'ugly']

更安全的方法(防止人手来escape的时候出错):

>>> import re
>>> delimiters = "a", "...", "(c)"
>>> example = "stackoverflow (c) is awesome... isn't it?"
>>> regexPattern = '|'.join(map(re.escape, delimiters))
>>> regexPattern
'a|\\.\\.\\.|\\(c\\)'
>>> re.split(regexPattern, example)
['st', 'ckoverflow ', ' is ', 'wesome', " isn't it?"]

改写成函数

def split(delimiters, string, maxsplit=0):
    import re
    regexPattern = '|'.join(map(re.escape, delimiters))
    return re.split(regexPattern, string, maxsplit)

方法 #1 的话如果你始终使用 os.path 或者 pymel.util.path 来处理路径的话,你就完全没有必要把 / \ 换来换去的,因为他们会自动处理 / \ , 同理你也用不着方法 #2的substitue了, 如果非要替换,可以用更强大的 re.sub

Related How-To’s

13 January 2002

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: