- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
这是我用来在 Autodesk Maya 中命名节点的命名脚本。然而,这个特定的脚本没有使用任何特定于 Maya 的内容。
我刚才问过我将如何着手做这样的事情,在哪里可以使用变量约定,然后出现了模板。
所以如果我有这样的约定:
'${prefix}_${name}_${side}_${type}'
我可以传递这些参数:
bind_thigh_left_joint
然后通过缩写字典(以及用户缩写字典)运行它们,与场景文件中的相关节点进行检查以确保没有重复项,最后得到:bn_thigh_L_jnt
但是我想要这样,如果其中一个键的第一个大写字母,它将使替代大写。
例如,如果 {$prefix}
改为 {$Prefix}
thigh 会变成 Thigh,或者如果 {$prefix}
是 {$PREFIX}
thigh 会变成 THIGH。然而,如果它是 {$PREfix}
thigh 仍然只是 Thigh。
我可以很容易地做到这一点,除了我无法检测键的个别情况。例如,如果字符串是 '${Prefix}_${name}_${SIDE}_${type}'
我如何找到大小写前缀,如果我知道的话,我如何将其与此模板一起使用?
请注意,这段代码与我的代码不完全一样,我省略了很多其他更具体的 Maya 内容,这只是处理替换本身。
from string import Template
import collections
def convert(prefix, name, side, obj_type):
user_conv = '${Prefix}_${name}_${SIDE}_${type}'
# Assigns keys to strings to be used by the user dictionary.
subs = {'prefix': prefix, 'name': name, 'side': side, 'type': obj_type}
# Converts all of user convention to lowercase, and substitutes the names from subs.
new_name = Template(user_conv.lower())
new_name = new_name.safe_substitute(**subs)
# Strips leading and trailing underscores, and replaces double underscores with a single
new_name = new_name.strip('_')
new_name = new_name.replace('__', '_')
return new_name
print convert('bind', 'thigh', 'left', 'joint')
>> bind_thigh_left_joint
编辑:还想去除多个下划线
所以如果我有类似的东西:
'${prefix}___${name}__${side}_____${type}'
我希望它出来
>> bind_thigh_left_joint
不是
>> bind___thigh__left____joint
还有最后一件事,我想既然用户会输入这个,那么不添加括号和美元符号会更方便。是否可以做这样的事情?
import re
user_conv = 'PREFIX_name_Side_TYPE01'
# do all filtering, removing of underscores and special characters
templates = ['prefix', 'name', 'side', 'type']
for template in templates:
if template in user_conv.lower():
# add bracket and dollar sign around match
>> '${PREFIX}_{name}_{Side}_${TYPE}01'
最佳答案
在这里,我们可以利用 OOP 的力量让模板做我们想做的事。我们可以继续扩展 string.Template
类(如 docs 中所建议)。
让我们先导入一些相关的方法/类:
from string import Template, uppercase, _multimap
import collections
然后我们定义一个辅助方法来处理传递给 safe_substitute()
的参数或 substitute()
方法。 (此方法的内容取自 Python 的 string
模块源):
def get_mapping_from_args(*args, **kws):
if len(args) > 1:
raise TypeError('Too many positional arguments')
if not args:
mapping = kws
elif kws:
mapping = _multimap(kws, args[0])
else:
mapping = args[0]
return mapping
然后我们继续定义我们的扩展模板类。让我们称这个类为CustomRenameTemplate
.我们编写了一个名为 do_template_based_capitalization()
的辅助方法,基本上是根据您提供的模板模式进行大写。我们确保覆盖 substitute()
和 safe_substitute()
使用它的方法。
class CustomRenameTemplate(Template):
def __init__(self, *args, **kws):
super(CustomRenameTemplate, self).__init__(*args, **kws)
self.orig_template = self.template
self.template = self.template.lower()
def do_template_based_capitalization(self, mapping):
matches = self.pattern.findall(self.orig_template)
for match in matches:
keyword = match[self.pattern.groupindex['braced']-1]
if keyword[0] in uppercase: # First letter is CAPITALIZED
if keyword == keyword.upper(): # Condition for full capitalization
mapping[keyword.lower()] = mapping[keyword.lower()].upper()
else: # Condition for only first letter capitalization
mapping[keyword.lower()] = mapping[keyword.lower()].capitalize()
def safe_substitute(self, *args, **kws):
mapping = get_mapping_from_args(*args, **kws)
self.do_template_based_capitalization(mapping)
return super(CustomRenameTemplate, self).safe_substitute(mapping)
def substitute(self, *args, **kws):
mapping = get_mapping_from_args(*args, **kws)
self.do_template_based_capitalization(mapping)
return super(CustomRenameTemplate, self).substitute(mapping)
我们现在可以使用这个类了。我们继续对您的 convert()
做一些细微的修改。将这个新类付诸实践的方法:
def convert(prefix, name, side, obj_type, user_conv='${Prefix}_${name}_${SIDE}_${type}'):
# Let us parameterize user_conv instead of hardcoding it.
# That makes for better testing, modularity and all that good stuff.
# user_conv = '${Prefix}_${name}_${SIDE}_${type}'
# Assigns keys to strings to be used by the user dictionary.
subs = {'prefix': prefix, 'name': name, 'side': side, 'type': obj_type}
# Converts all of user convention to lowercase, and substitutes the names from subs.
new_name = CustomRenameTemplate(user_conv) # Send the actual template, instead of it's lower()
new_name = new_name.substitute(**subs)
# Strips leading and trailing underscores, and replaces double underscores with a single
new_name = new_name.strip('_')
new_name = new_name.replace('__', '_')
return new_name
这是实际操作:
>>>print convert('bind', 'thigh', 'left', 'joint')
Bind_thigh_LEFT_joint
>>>print convert('bind', 'thigh', 'left', 'joint', user_conv='${prefix}_${name}_${side}_${type}')
bind_thigh_left_joint
>>>print convert('bind', 'thigh', 'left', 'joint', user_conv='${prefix}_${NAme}_${side}_${TYPE}')
bind_Thigh_left_JOINT
如果要处理多次出现的下划线 _
和用户约定中可能的特殊字符,只需在 return
之前添加以下行convert()
的声明方法:
new_name = re.sub('[^A-Za-z0-9_]+', '', new_name) # This will strip every character NOT ( NOT is denoted by the leading ^) enclosed in the []
new_name = re.sub('_+', '_', new_name) # This will replace one or more occurrences of _ with a single _
注意:剥离特殊字符时需要考虑的重要事项是 Maya egs 使用的特殊字符。用于命名空间表示 :
和层次结构表示 |
.我将由您决定是选择剥离这些,还是用另一个角色替换它们,或者一开始就不接收它们。大多数返回对象名称的 Maya 命令都有标志来控制返回名称的详细程度(例如,WITH 命名空间、完整的 DAG 路径,或者这些都不是)。
对于你问题的扩展部分,你问过的地方:
Also the last thing, I figured since a user would be inputting this, it would be more convenient not to be adding brackets and dollar signs. Would it be possible to do something like this?
是的。事实上,为了进一步推广,如果您假设模板字符串仅由字母而不是字母数字组成,您可以再次使用 re
从 user_conv
中挑选它们把它们塞进去${}
像这样:
user_conv = 'PREFIX_name_Side_TYPE01'
user_conv = re.sub('[A-Za-z]+', '${\g<0>}', user_conv)
>>> print user_conv
>>> ${PREFIX}_${name}_${Side}_${TYPE}01
我们在这里使用了反向引用的力量,即 \g<group_number>
.检查docs here有关正则表达式中反向引用的更多信息。
关于区分大小写的 Python 字符串模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28851063/
如何使用 SPListCollection.Add(String, String, String, String, Int32, String, SPListTemplate.QuickLaunchO
我刚刚开始使用 C++ 并且对 C# 有一些经验,所以我有一些一般的编程经验。然而,似乎我马上就被击落了。我试过在谷歌上寻找,以免浪费任何人的时间,但没有结果。 int main(int argc,
这个问题已经有答案了: In Java 8 how do I transform a Map to another Map using a lambda? (8 个回答) Convert a Map>
我正在使用 node + typescript 和集成的 swagger 进行 API 调用。我 Swagger 提出以下要求 http://localhost:3033/employees/sear
我是 C++ 容器模板的新手。我收集了一些记录。每条记录都有一个唯一的名称,以及一个字段/值对列表。将按名称访问记录。字段/值对的顺序很重要。因此我设计如下: typedef string
我需要这两种方法,但j2me没有,我找到了一个replaceall();但这是 replaceall(string,string,string); 第二个方法是SringBuffer但在j2me中它没
If string is an alias of String in the .net framework为什么会发生这种情况,我应该如何解释它: type JustAString = string
我有两个列表(或字符串):一个大,另一个小。 我想检查较大的(A)是否包含小的(B)。 我的期望如下: 案例 1. B 是 A 的子集 A = [1,2,3] B = [1,2] contains(A
我有一个似乎无法解决的小问题。 这里...我有一个像这样创建的输入... var input = $(''); 如果我这样做......一切都很好 $(this).append(input); 如果我
我有以下代码片段 string[] lines = objects.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.No
这可能真的很简单,但我已经坚持了一段时间了。 我正在尝试输出一个字符串,然后输出一个带有两位小数的 double ,后跟另一个字符串,这是我的代码。 System.out.printf("成本:%.2
以下是 Cloud Firestore 列表查询中的示例之一 citiesRef.where("state", ">=", "CA").where("state", "= 字符串,我们在Stack O
我正在尝试检查一个字符串是否包含在另一个字符串中。后面的代码非常简单。我怎样才能在 jquery 中做到这一点? function deleteRow(locName, locID) { if
这个问题在这里已经有了答案: How to implement big int in C++ (14 个答案) 关闭 9 年前。 我有 2 个字符串,都只包含数字。这些数字大于 uint64_t 的
我有一个带有自定义转换器的 Dozer 映射: com.xyz.Customer com.xyz.CustomerDAO customerName
这个问题在这里已经有了答案: How do I compare strings in Java? (23 个回答) 关闭 6 年前。 我想了解字符串池的工作原理以及一个字符串等于另一个字符串的规则是
我已阅读 this问题和其他一些问题。但它们与我的问题有些无关 对于 UILabel 如果你不指定 ? 或 ! 你会得到这样的错误: @IBOutlet property has non-option
这两种方法中哪一种在理论上更快,为什么? (指向字符串的指针必须是常量。) destination[count] 和 *destination++ 之间的确切区别是什么? destination[co
This question already has answers here: Closed 11 years ago. Possible Duplicates: Is String.Format a
我有一个Stream一个文件的,现在我想将相同的单词组合成 Map这很重要,这个词在 Stream 中出现的频率. 我知道我必须使用 collect(Collectors.groupingBy(..)
我是一名优秀的程序员,十分优秀!