bpy.ops.object.select_pattern
As mentioned in your previous question re the operator script Script is selecting all the objects (unwanted) there is already a pattern matching operator, bpy.ops.object.select_pattern
which uses Unix file token matching. See no need to "reinvent the wheel" and write another, which so far has no extra functionality. Here is quick run down on how it works. (The code of the operator is available in bl_operators/object.py
.)
>>> bpy.ops.object.select_pattern(
select_pattern()
bpy.ops.object.select_pattern(pattern="*", case_sensitive=False, extend=True)
Select objects matching a naming pattern
options to extend the selection, and a case insensitive match.
>>> import fnmatch
>>> fnmatch.fnmatch(
fnmatch(name, pat)
Test whether FILENAME matches PATTERN.
Patterns are Unix shell style:
* matches everything
? matches any single character
[seq] matches any character in seq
[!seq] matches any char not in seq
An initial period in FILENAME is not special.
Both FILENAME and PATTERN are first case-normalized
if the operating system requires it.
If you don't want this, use fnmatchcase(FILENAME, PATTERN).
So for example sake will pinch
>>> txt = {"US40.004", "US40.005", "US41.001", "US51.006", "US-009.009", "US-009.010", "US-015", "US-016", "USA", "USADOT"}
make a pattern, Case sensitive, any name starting with "US" but not having an uppercase character as third character. then end with anything
>>> pattern = "US[!A-Z]*"
>>> for t in txt:
... t, fnmatch.fnmatchcase(t, pattern)
...
('US-009.009', True)
('US40.005', True)
('US41.001', True)
('US51.006', True)
('US-016', True)
('US-009.010', True)
('USA', False)
('USADOT', False)
('US-015', True)
('US40.004', True)
Looks about right, so a call with instead object names matching the sample list
bpy.ops.object.select_pattern(pattern="US[!A-Z]*", case_sensitive=True)
in object mode will select all objects denoted True above
To clarify, re the commentary below, it is not necessary to use the operator could (thought this was implied TBH) instead
for ob in scene.objects:
ob.select_set(fnmatch.fnmatchcase(ob.name, pattern)) # match case
Re setting the active object. If the context object is no longer selected, or None
and you wish it to be one of the selected
if context.selected_objects and context.object not in context.selected_objects:
context.view_layer.objects.active = context.selected_objects[0]
ie If the active object is set and selected probably don't want to randomly change it to another of the selected objects. (BTW most selection operators do not set the active object)