It is currently September 24th, 2024, 10:30 pm

Regexpsubstitute doesn't work the way I need it to.

Get help with creating, editing & fixing problems with skins
Kotofanchik
Posts: 167
Joined: March 15th, 2024, 7:30 pm

Regexpsubstitute doesn't work the way I need it to.

Post by Kotofanchik »

I needed to find numbers in the string variable. The first, second, third number among other symbols. And I noticed that the mask I'm searching for gives me not the first, but the last match. Is this somehow regulated? Maybe Regexpsubstitute finds the first match like a web parser? And not the last?
For now, I got out of the situation by turning the string backwards, which is not very convenient.
User avatar
ikarus1969
Posts: 590
Joined: February 28th, 2011, 3:20 pm
Location: Vienna, Austria

Re: Regexpsubstitute doesn't work the way I need it to.

Post by ikarus1969 »

Please post a piece of text you are searching for and the regular expression you use so far. It's not easy (at least for me) to really understand where the problem is. With the text you are searching and the regular expression you are using i can follow better.

edit: one idea is to use the option (?U), which means "ungreedy". you have to place that at the beginning of your regular expression. Maybe that helps; but anyway: please post text and the regular expression you are using so far.
User avatar
sl23
Posts: 1743
Joined: February 17th, 2011, 7:45 pm
Location: a Galaxy S7 far far away

Re: Regexpsubstitute doesn't work the way I need it to.

Post by sl23 »

Out of curiosity, still trying to learn the basics of regex, can you use (0-100) if searching for 3 digit numbers?
57686174 77696C6C 6265 77696C6C 6265
Kotofanchik
Posts: 167
Joined: March 15th, 2024, 7:30 pm

Re: Regexpsubstitute doesn't work the way I need it to.

Post by Kotofanchik »

here is the text :z:z:160:z:z:z:460:z:
I need to capture the first digit 160 with one capture and 460 with another
Here is the expression

regexpsubstitute=1
substitute=".*:(\d+):.*":"\1"
I expect it to return 160, but it returns 460
That is, the last match. The input string itself can be much longer and have more digits, but I am only interested in the first two numbers.

I tried substitute="(?U).*:(\d+):.*":"\1"
I got a completely incomprehensible 160460z:
I guess that I added it incorrectly and (?U) worked as a capture, but I don't understand how to do it correctly
User avatar
balala
Rainmeter Sage
Posts: 16585
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Regexpsubstitute doesn't work the way I need it to.

Post by balala »

Kotofanchik wrote: Today, 10:15 am here is the text :z:z:160:z:z:z:460:z:
I need to capture the first digit 160 with one capture and 460 with another
Here is the expression

regexpsubstitute=1
substitute=".*:(\d+):.*":"\1"
I expect it to return 160, but it returns 460
Try this substitution: Substitute="(?U)^.*:(\d+):.*$":"\1"
Kotofanchik
Posts: 167
Joined: March 15th, 2024, 7:30 pm

Re: Regexpsubstitute doesn't work the way I need it to.

Post by Kotofanchik »

balala wrote: Today, 11:51 am Try this substitution: Substitute="(?U)^.*:(\d+):.*$":"\1"
Yes, it works as it should, thank you
User avatar
balala
Rainmeter Sage
Posts: 16585
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Regexpsubstitute doesn't work the way I need it to.

Post by balala »

Kotofanchik wrote: Today, 12:32 pm Yes, it works as it should, thank you
You're welcome.
User avatar
Yincognito
Rainmeter Sage
Posts: 8225
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Regexpsubstitute doesn't work the way I need it to.

Post by Yincognito »

Just so it's clear why that happened: since ".*:(\d+):.*" doesn't have any kind of "anchor" at the beginning or end to know from where and to where to do the substitute, it does it everywhere (i.e. on each match) in the string, that's why the former attempt didn't succeed as desired. Generally speaking, it's almost mandatory to use some kind of anchor to "lock" the pattern to a certain area of the string if you need to substitute only one occurrence and not all, that's why balala's suggestion worked (that and the ?U ungreedy flag to match as few chars as possible with the * quantifier, of course).

By the way, it's not often used, but a ? after the first * quantifier, to make the pattern "^.*?:(\d+):.*$" has the same effect as using the ?U flag here. What ? does after a quantifier is to locally "invert the greediness" (or lack of, if ?U is used) set by the presence or absence of ?U. The ? acts locally where used, while ?U acts globally on the entire string.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 8225
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Regexpsubstitute doesn't work the way I need it to.

Post by Yincognito »

As for "using (0-100) if searching for 3 digit numbers", the typical way is to use either \d\d\d or \d{3} for that, but of course that would match any 3 digit number, i.e. from 000 to 999.

Since regex can't "iterate" or "count" in a pattern other than counting how many times a pattern occurs, if only 0 to 100 with no zero padding is desired, a regex like (\d|[1-9]\d|100) to capture it, or (?:\d|[1-9]\d|100) to not capture it is more suited for that, since it would match all 1 digit numbers (i.e. 0...9) OR all 2 digits numbers that don't start with 0 (i.e. 10..99) OR 100. The | means the logical OR, while 1-9 means characters (and not numbers in the mathematical sense, since regex only works with strings and has no "understanding" of numbers) from 1 to 9 in the ASCII / Unicode table.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth