使用format命令扩展参数

时间:2016-03-08 06:00:51

标签: tcl

我遇到了一个场景,我需要在{*}命令中使用参数扩展。使用Tcl8.5,我使用的是eval,它就像魅力一样。

但是,使用Tcl8.4,我尝试了% set x "This is stackoverflow" This is stackoverflow % format "%10s %5s %20s" {*}$x This is stackoverflow % eval format "%10s %5s %20s" $x %5s % eval list format "%10s %5s %20s" $x format %10s %5s %20s This is stackoverflow % eval [list format "%10s %5s %20s" $x] not enough arguments for all format specifiers % eval format "%10s %5s %20s" [list $x] %5s % eval format "%10s %5s %20s" [concat $x] %5s 。但是,没有运气。

var obj = editor.selected;
var tex = obj.material.map.;

var materials = [];
materials.push(new THREE.MeshBasicMaterial({ map: tex }));
materials.push(new THREE.MeshBasicMaterial({}));

var material = new THREE.MeshFaceMaterial(materials);

var objHeight = obj.geometry.parameters.height;
var objWidth = obj.geometry.parameters.width;
var texHeight = tex.image.height;
var texWidth = tex.image.width;

tex.repeat = new THREE.Vector2(3, 3);
tex.offset = new THREE.Vector2(0, 0);

var geometry = new THREE.PlaneGeometry(objWidth, objHeight, 3, 3);

var v = geometry.vertices;
var facesNum = geometry.faces.length;

v[1] = new THREE.Vector3(-texWidth / 2, objHeight / 2, 0);
v[2] = new THREE.Vector3(texWidth / 2, objHeight / 2, 0);
v[5] = new THREE.Vector3(-texWidth / 2, (objHeight / 2) - texHeight, 0);
v[6] = new THREE.Vector3(texWidth / 2, (objHeight / 2) - texHeight, 0);

v[9] = v[13];
v[10] = v[14];
v[4] = v[8] = v[12];
v[7] = v[11] = v[15];

for (var i = 0; i < facesNum; i++) {
    if (i !== 2 && i !== 3) geometry.faces[i].materialIndex = 1;
}

obj.material = material;
obj.geometry = geometry;

editor.signals.materialChanged.dispatch(obj);

这里我的错误是什么?

3 个答案:

答案 0 :(得分:3)

请参阅本文的eval and double substitution部分。

正确的方法是:

eval "format {%10s %5s %20s} $x"

这里eval无法连接任何参数,因此获取解释器的是替换形式:format {%10s %5s %20s} This is stackoverflow。你当然可以使用eval "format \"%10s %5s %20s\" $x",但我更愿意尽可能避免使用反斜杠转义。

eval format "%10s %5s %20s" $x

错误是因为eval首先将字符串连接在一起,所以最终得到:

eval format %10s %5s %20s $x

这就像说format %10s %5s %20s $x,这就是为什么你得到你得到的东西)

eval list format "%10s %5s %20s" $x

变为:

eval list format %10s %5s %20s $x

这就像说list format %10s %5s %20s $x并且没有让format真正做某事。

eval [list format "%10s %5s %20s" $x]

方向正确,但$x没有扩展,所以你正在做format "%10s %5s %20s" $x

其他人只将$x放入更深的列表中,或者在这种情况下不会改变任何内容。

答案 1 :(得分:3)

8.4成语是使用linsert来创建要评估的命令

set x "This is stackoverflow"
set args [split $x]
set cmd [linsert $args 0 format "%10s %5s %20s"]
set formatted [eval $cmd]

或嵌套在一行

set formatted [eval [linsert [split $x] 0 format "%10s %5s %20s"]]

答案 2 :(得分:1)

如果编写concat-and-evaluate命令(如eval)的调用方式不明确,那么用concat替换命令通常会有助于查看将要执行的操作评估,例如concat format "%10s %5s %20s" $x代替eval format "%10s %5s %20s" $x

这些表单展平格式化字符串,使第二个格式说明符成为第一个值参数(前两个是等价的,$x是一个平面列表,因此与[concat $x相同]:)

concat format "%10s %5s %20s" $x
# -> format %10s %5s %20s This is stackoverflow
concat format "%10s %5s %20s" [concat $x]
# -> format %10s %5s %20s This is stackoverflow
concat format "%10s %5s %20s" [list $x]
# -> format %10s %5s %20s {This is stackoverflow}

此表单还插入了不属于该列表的列表命令:

concat list format "%10s %5s %20s" $x
# -> list format %10s %5s %20s This is stackoverflow

此表单保留格式化字符串的列表结构,但遗憾的是还保留了$x的列表结构:

concat [list format "%10s %5s %20s" $x]
# -> format {%10s %5s %20s} {This is stackoverflow}

这两种形式做正确的事情:它们保留格式化字符串,但展平参数列表:

concat "format {%10s %5s %20s} $x"
# -> format {%10s %5s %20s} This is stackoverflow
concat [list format {%10s %5s %20s}] $x
# -> format {%10s %5s %20s} This is stackoverflow

文档:concatevalformatlist