Pregunta

I'm writing a recursive procedure, called "subliner3". To be simple it replaces:

  1. [object method] with Object->method()
  2. [object method:attr1 attr2 ...] with object->method(attr1,attr2,...)

It is recursive to replace (1) and (2) inside (2). Any attr may be like (1) or (2).

So, this code causes problem:

while {[regsub -all {\[([^\[\]:]+)[:]([^\[\]]+)\]} $subline "[subliner3 "\\1" "\\2"]" subline]} {}

This is supposed to find exactly (2) in subline (subline is an attribute list) and call function again for it. The problem is that, when subline is called with regsub's \1 and \2 subliner3 really gets "\1" and "\2", so looks like they are interpreted afted subliner3 call. How can I manage to call [subliner3 "\1" "\2"] with interpreted \1 & \2?

Sample Input:

[self runAction:[CCSequence actions:[CCDelayTime actionWithDuration:5], [CCCallFunc actionWithTarget:self selector:@selector(resetMessage)], nil]]; 

Output:

self->runAction(CCSequence::actions(CCDelayTime::actionWithDuration(5), CCCallFunc::actionWithTarget(self, @selector(resetMessage)), nil);
¿Fue útil?

Solución

You can do it (under some assumptions, such as no use of arrays) but you really need to work inside out and to put your substitution code in a loop.

# Your sample as input
set string {[self runAction:[CCSequence actions:[CCDelayTime actionWithDuration:5], [CCCallFunc actionWithTarget:self selector:@selector(resetMessage)], nil]];}

# Do most of the replacements, recursively.
#
# Note that some parts are changed to \001stripExtra stuff\002, because we need
# to do further processing on the arguments which can't quite be done in this
# looped [regsub].
while {[regsub -all {\[(\w+) (\w+):([^]]+)\]} $string \
        "\\1::\\2(\u0001stripExtra \\3\u0002)" string]} {}

# The further processing to do on arguments (removing selectors)
proc stripExtra args {
    foreach s $args {
        # The lack of a fourth argument means [regsub] returns the string
        lappend t [regsub {^\w+:(?!:)} [string trimright $s ","] {}]
    }
    return [join $t ","]
}
# Apply the further processing by converting to a substitutable string
set string [subst [string map {\u0001 "\[" \u0002 "\]"} $string]]

# Now transformed...
puts $string

The code above is rather brittle as it doesn't actually understand Objective-C, so you should check that its output is reasonable on your real input data…

Otros consejos

One of possible solutions is: expr \"[regsub -all {(1)} "number 1" "[getSp \1]"]\" So, at first, regsub manages to put (1) on \1 position. Then expr makes to call getSp. And it will be called not with \1, but with (1). But to work with this solution I need to make sure, that string, returned by regsub has [ ] specified only for procedures, but it is not allways like that. For example string after regsub call may be like that: [self runAction:[CCSequence actions:[subliner3 "CCDelayTime actionWithDuration" "5"], [subliner3 "CCCallFunc actionWithTarget" "self selector:@selector(resetMessage)"], nil]]; Where only subliner3 - is a procedure.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top