Remove number sequence from object name

Remove number sequence from object name

chad_voller
Participant Participant
1,145 Views
10 Replies
Message 1 of 11

Remove number sequence from object name

chad_voller
Participant
Participant

As the title says, I'm trying to remove the ending number sequence from a selection of objects. Sometimes it's 2 digits, sometimes 3 digits, depending on how the object was copied/instanced. And sometimes it's many more digits if it's a CAD import. So if I have something named, LP45_Object039871, I want to have it identify the sequence 039871 at the end of the name and remove it so it will be LP45_Object with no sequence at the end. Sometimes there's an "_" or "-" before the sequence that should be removed as well. Is this possible in Maxscript?

0 Likes
Accepted solutions (2)
1,146 Views
10 Replies
Replies (10)
Message 2 of 11

MartinBeh
Advisor
Advisor

Sure!

For each object get name

   walk forward from the end of the name until you hit a letter

   use the remaining part as new name

Martin B   EESignature
→ please 'Like' posts that are helpful; if a post answers your question please click the "Accept Solution" button.
0 Likes
Message 3 of 11

chad_voller
Participant
Participant

How exactly is that done? I can't seem to figure out how to differentiate between characters in the name. What tells it that it is a number, or _ or -?

0 Likes
Message 4 of 11

MartinBeh
Advisor
Advisor
Accepted solution

The cool kids might simply use regular expressions in dotNet to get the new name but here is how to do it with only built-in MAXscript tools:

 

 

fn isChar txt =  (toUpper (toLower txt)) != txt
-- hack: test if changing case of txt changes txt - if yes then txt is not characters

fn trimNonChar txt = (
	-- remove any non-letter from the end of txt
	local pos = txt.count
	local cont = true
	for i = txt.count to 1 by -1 while cont do (
		pos = i
		if (isChar txt[i]) then cont = false
	)
	substring txt 1 pos
)

-- select all objects you want to be renamed
for o in selection do (
	local newName = trimNonChar o.name
	format "Renaming % to %\n" o.name newName
	-- comment next line out for a dry run
	o.name = newName
)

 

Martin B   EESignature
→ please 'Like' posts that are helpful; if a post answers your question please click the "Accept Solution" button.
Message 5 of 11

MartinBeh
Advisor
Advisor

But note: This will rename "Sphere001", "Sphere_002" and "Sphere0003" all into "Sphere".

 

3ds max allows you to have multiple objects with the same name, but IMO this is a very bad idea. 

Martin B   EESignature
→ please 'Like' posts that are helpful; if a post answers your question please click the "Accept Solution" button.
0 Likes
Message 6 of 11

MartinBeh
Advisor
Advisor

Or you get the integer representation of a single character and compare that:

 

 

fn isChar txt = bit.charAsInt txt >= 65

 

See https://www.ascii-code.com/ for the numbers. If you also want to remove "_" you need to test for value 95

 

Martin B   EESignature
→ please 'Like' posts that are helpful; if a post answers your question please click the "Accept Solution" button.
0 Likes
Message 7 of 11

MartinBeh
Advisor
Advisor
Accepted solution

Here is a drop-in replacement that uses dotNet regex:

 

fn trimNonChar txt = (
	local regex = dotnetobject "System.Text.RegularExpressions.Regex" @"[_-]*\d{3,}$"	-- search for 3 or more digits at the end, optionally preceeded by one ore more _ or - characters
	local match = regex.matches txt
	if match.count == 1 then (
		substring txt 1 (txt.count - match.item[0].length)		-- trim away end
	) else txt
)

 

Martin B   EESignature
→ please 'Like' posts that are helpful; if a post answers your question please click the "Accept Solution" button.
Message 8 of 11

MartinBeh
Advisor
Advisor

And one more variant, even shorter - this time using Python and the same regular expression:

 

 

global py_re = python.import "re"   -- load Python's regular expression module
fn trimNonChar txt = (
	::py_re.sub @"[_-]*\d{3,}$" "" txt  -- using Python, replace _-ddd... with nothing and return
)

-- select all objects you want to be renamed, then run this
for o in selection do (
	local newName = trimNonChar o.name
	format "Renaming % to %\n" o.name newName
	-- comment next line out for a dry run
	o.name = newName
)

 

 

 

Martin B   EESignature
→ please 'Like' posts that are helpful; if a post answers your question please click the "Accept Solution" button.
0 Likes
Message 9 of 11

chad_voller
Participant
Participant

That is exactly what I am looking for. And yes, I do agree that having objects of the same name is a bad idea. I'm working with 3rd party software that requires the names to be exactly the same, and removing the number sequence fixes that. I will be putting in some safeguards that it is only applied to the correct objects, and possibly on export only. I appreciate the different options you gave to get the result.

0 Likes
Message 10 of 11

denisT.MaxDoctor
Advisor
Advisor
fn trimTailDigits str spec:" _-." = trimright str ("0123456789" + spec)

trimTailDigits "string_test_0001"
trimTailDigits #string_test_02
0 Likes
Message 11 of 11

denisT.MaxDoctor
Advisor
Advisor

here is specifically for node object names:

 

mapped fn trimName node chars:" _-.0123456789" = (node.name = trimright node.name chars)

for k=1 to 10 do box()
trimName objects