Add leading zeros to 3-part number string

Advanced Renamer forum
#1 : 22/07-21 00:41
Sailor Guy
Sailor Guy
Posts: 40
I have a folder naming format of:

1.10.5 - Sieman SFPH10GB2MS03
9.7.3 - Another server
23.456.78 - Another computer

I would like to pad the 3-part number string with padded zeros:

01.010.05 - Sieman SFPH10GB2MS03 (leading zeros added)
09.007.03 - Another server (leading zeros added)
23.456.78 - Another computer (no changes)

So far I have:

Text to be replaced: (\d+).(\d+).(\d+) -(.*)
Replace with: $1.$2.$3 - $4
Occurrence: 1st
Use regular expressions - checked
Apply to: Name

But I don't know how to make the first token 2-digits, the second token 3-digits, and the third token 2-digits - all with leading zeros.

Can someone please help me over the finish line?

Thank you,

Sailor Guy


22/07-21 00:41 - edited 22/07-21 04:54
#2 : 22/07-21 09:03
David Lee
David Lee
Posts: 1125
Just use three Renumber methods to pad each number separately..

Number position: 1
Change to: Relative to existing number
Number difference: 0
Zero padding: Manual
Number length: 2

Similarly for the 2nd & 3rd numbers.

Alternatively you can use your regular expression in a Script method:

name = item.name;
match = name.match(/(\d+).(\d+).(\d+)(.*)/);
return ('00' + match[1]).slice(-2) + '.'
+ ('000' + match[2]).slice(-3) + '.'
+ ('00' + match[3]).slice(-2) + match[4];


22/07-21 09:03
#3 : 22/07-21 14:15
Sailor Guy
Sailor Guy
Posts: 40
Thank you, David!

I chose option 1 - the 3 Renumber methods

Worked like a charm.

As always, I appreciate your timely support!

Sailor Guy


22/07-21 14:15
#4 : 23/07-21 16:47
Sailor Guy
Sailor Guy
Posts: 40
Hi, David,

I decided to try the script version (rather than renumber) to see what happens and I receive this error message on every folder:

Invalid script: Invalid post script: uncaught: 'cannot read property 1 of null'

This is what I have in the script window:

name = item.name;

match = name.match(/(\d+).(\d+).(\d+)(.*)/);

return ('00' + match[1]).slice(-2) + '.'
+ ('000' + match[2]).slice(-3) + '.'
+ ('00' + match[3]).slice(-2) + match[4];

I googled javascript match and slice but can't determine what's causing the error.

Can you please provide some guidance?

Thank you,

Sailor Guy


23/07-21 16:47
#5 : 23/07-21 20:07
David Lee
David Lee
Posts: 1125


23/07-21 20:07 - edited 23/07-21 20:17
#6 : 23/07-21 20:07
David Lee
David Lee
Posts: 1125
Reply to #4:
The script works for the examples you gave, where the regex /(\d+).(\d+).(\d+)(.*)/ matches the folder name. The match will return an array of which the first element contains the entire match and subsequent elements contain the values of the individual matched sub-patterns.

For example...
match = '1.10.5 - Sieman SFPH10GB2MS03'.match(/(\d+).(\d+).(\d+)(.*)/);
will return an array:
match[0] = '1.10.5
match[1] = '1'
match[2] = '10'
match[3] = '5'
match[4] = ' - Sieman SFPH10GB2MS03'

However if the regex fails to find a match it will return a single value: null and any attempt to extract an array element (x) from this value will result in the error: 'cannot read property x of null'.

Unfortunately, for some odd reason, if even only one folder name does not return a match you will see the same error for every folder.

The solution is to check that "match" is not null before trying to extract the individual sub-pattern matches as array elements:

name = item.name;
match = name.match(/(\d+).(\d+).(\d+)(.*)/);
if (match) {
return ('00' + match[1]).slice(-2) + '.'
+ ('000' + match[2]).slice(-3) + '.'
+ ('00' + match[3]).slice(-2) + match[4];name = item.name;
}





23/07-21 20:07 - edited 23/07-21 20:25
#7 : 23/07-21 20:35
Sailor Guy
Sailor Guy
Posts: 40
David,

I tried the new conditional logic and this time I get this error message:

if (match) {
return ('00' + match[1]).slice(-2) + '.'
+ ('000' + match[2]).slice(-3) + '.'
+ ('00' + match[3]).slice(-2) + match[4];name = item.name;
}

Invalid script: Invalid post script: uncaught: 'identifier \x27match\x27' undefined'

I should point that not every folder in the list starts with a 1.2.3 numeric string.

Some folders have different names like:
"_Documents"
"_NotApplicableTests"
"177_03_13_05"

I appreciate your continued assistance on this.

Sailor Guy


23/07-21 20:35
#8 : 24/07-21 11:32
David Lee
David Lee
Posts: 1125
Reply to #7:
That error means that the variable 'match' is not defined in the script.

I notice that the code you posted in Reply #7 is missing the first two lines of my script, which would generate the error that you describe:

name = item.name;
match = name.match(/(\d+).(\d+).(\d+)(.*)/);
if (match) {
return ('00' + match[1]).slice(-2) + '.'
+ ('000' + match[2]).slice(-3) + '.'
+ ('00' + match[3]).slice(-2) + match[4];name = item.name;
}


24/07-21 11:32
#9 : 24/07-21 15:40
Sailor Guy
Sailor Guy
Posts: 40
Hi, David,

Okay, we’re almost there.

First of all, you were correct – I had forgotten to copy the two top statements. Duh!!

However, I still have one more issue to resolve…

I made a couple changes to the script based on my actual list of folder names and the other methods that precede and follow this script method in this AREN method list:

Here are my folder names:

5.004 Test 1.3 - Install NXOS Feature Licenses
5.005 Test 1.4 - HW Steady State
5.006 Test 1.5 - USB Port
5.007 Test 1.6 - Redundant Power Supply Failover
5.008 Test 1.7.1 - Redundant Fan Failover
5.009 Test 1.7.2 - Forward Airflow
5.010 Test 1.7.3 - Reverse Airflow
5.011 Test 1.7.4 - Standard Template Commands
5.011 Test 1.7.4 - Standard Template Commands
5.042 Test 1.14.1 - Console Access
5.043 Test 1.14.2 - Local Access
5.044 Test 1.14.3 - AAA & TACACS Functionality
5.045 Test 1.14.4 - SSH(v2) Functionality

The number string (which follows the word “Test”) can be a 2-token “1.2” or 3-token “1.2.3” format

I have a script that has 10 different methods. Right now, I’m only concerned about the first 3. The other 7 work fine.

Method 1: Replace “*Test “ with nothing to remove all text up to the number string
Method 2: Script: I use your (modified) script to fix the 3-token number strings
Method 3: Script: I use your (modified) script to fix the 2-token number strings

Here is the Method 2 (modified) script (to correct the 3-token numbers 1.2.3):

//name = item.name;
name = item.newName;
match = name.match(/(\d+).(\d+).(\d+) - (.*)/);
if (match) {
sNewName=('00' + match[1]).slice(-2) + '.'
+ ('000' + match[2]).slice(-3) + '.'
+ ('00' + match[3]).slice(-2) + " -- " + match[4];
//sNewName = sNewName.substr(0,sNewName.lastIndexOf("."));
return sNewName;
name = item.name;
}

The problem is the part of the folder name is being repeated:

“1.5 - USB Port” -> “01.005 – USB Port.5 – USB port”
“1.7.2 - Forward Airflow” -> “01.007.02 – Forward Airflow.2 – Forward Airflow”

I believe this is because folders don’t have extensions and I have to handle that fact in my script.

I added the following SUBSTR statement thinking it would parse off the duplicated part of the folder name (which is essentially the extension since it follows the last “.” in the folder name) – but it doesn’t work as I expected:

sNewName = sNewName.substr(0,sNewName.lastIndexOf("."));

“1.7.2 - Forward Airflow” -> “007.02 – Forward Airflow.2 – Forward Airflow”

Can you please provide the correct syntax to remove the duplicated portion of the folder name?

Thank you,

Sailor Guy







24/07-21 15:40
#10 : 25/07-21 02:49
David Lee
David Lee
Posts: 1125
Reply to #9:
You have already spotted the problem! ARen is treating everything after the last dot as an extension when it returns the new filename. The solution is to select 'Apply to' = 'Name and extension' at the bottom of the Script method window.

The following code should carry out all three methods in a single script:

name = item.newName.replace(/^.*Test /,'');
match = name.match(/(\d+).(\d+)(\.\d+)?(.*)/);
if (match) {
newName = ('00' + match[1]).slice(-2) + '.' + ('000' + match[2]).slice(-3);
if (match[3]) newName += '.' + ('00' + match[3].match(/\d+/)).slice(-2);
newName += match[4];
return newName;
}


25/07-21 02:49 - edited 25/07-21 02:50
#11 : 25/07-21 05:17
Sailor Guy
Sailor Guy
Posts: 40
Yep, David, that did it!

Works perfectly now.

You write very compact code! I need to study the new script so I understand the regex better.

I may have to modify the script to also handle a 4-token format... 01.002.03.04. I'll see if I can manage it myself with the great start you've given me.

Thanks, as always, David, for shining the light on some regex and JS scripting darkness! ;^;

Sailor Guy


25/07-21 05:17
#12 : 25/07-21 11:33
David Lee
David Lee
Posts: 1125
Reply to #11:

Two hints:

1) 'a += b;' is equivalent to 'a = a + b;'

2) In 'match = name.match(/(\d+).(\d+)(\.\d+)?(.*)/);' :
'(\.\d+)?' will match a dot followed by a string of one or more digits and save the result in a variable as usual. However, the addition of the question mark indicates to carry out the match zero or one times, so the overall regex will still match if the third number group is absent - but in which case the sub-pattern will return 'null'.


25/07-21 11:33
#13 : 25/07-21 20:00
Sailor Guy
Sailor Guy
Posts: 40
Thanks for the hints and explanation.

Sailor Guy


25/07-21 20:00