Regex - excluding characters - regex

I am trying to create a pattern that will ignore starting from Всего word and just will capture the number 2501,472 at the end -> Всего 191 Короб-шкаф вес БРУТТО 2501,472
Also, i am trying to include word change possibilities [^Короб-шкаф|Коробка] which is working fine in another pattern i have created
([^Всего]?[^\\d]*?[^Короб-шкаф|Коробка]\s*[^вес БРУТТО\\s*] \\d,]*)

Converting my comment to answer so that solution is easy to find for future visitors.
You may use this alternation regex that uses a capture group where we are capturing number that appears after a known pattern:
\\bВсего\\h+\\d+\\h+(?:Короб-шкаф|Коробка)\\h+вес\\h+БРУТТО\\h+([\\d,]+)
Then use captured group #1 for your number comprising digits and comma characters.

Related

Extra groups in regex

I'm building a regex to be able to parse addresses and am running into some blocks. An example address I'm testing against is:
5173B 63rd Ave NE, Lake Forest Park WA 98155
I am looking to capture the house number, street name(s), city, state, and zip code as individual groups. I am new to regex and am using regex101.com to build and test against, and ended up with:
(^\d+\w?)\s((\w*\s?)+).\s(\w*\s?)+([A-Z]{2})\s(\d{5})
It matches all the groups I need and matches the whole string, but there are extra groups that are null value according to the match information (3 and 4). I've looked but can't find what is causing this issue. Can anyone help me understand?
Your regex expression was almost good:
(^\d+\w?)\s([\w*\s?]+).\s([\w*\s?]+)\s([A-Z]{2})\s(\d{5})
What I changed are the second and third groups: in both you used a group inside a group ((\w*\s?)+), where a class inside a group (([\w*\s?]+)) made sure you match the same things and you get the proper group content.
With your previous syntax, the inner group would be able to match an empty substring, since both quantifiers allow for a zero-length match (* is 0 to unlimited matches and ? is zero or one match). Since this group was repeated one or more times with the +, the last occurrence would match an empty string and only keep that.
For this you'll need to use a non-capturing group, which is of the form (?:regex), where you currently see your "null results". This gives you the regex:
(^\d+\w?)\s((?:\w*\s?)+).\s(?:\w*\s?)+([A-Z]{2})\s(\d{5})
Here is a basic example of the difference between a capturing group and a non-capturing group: ([^s]+) (?:[^s]+):
See how the first group is captured into "Group 1" and the second one is not captured at all?
Matching an address can be difficult due to the different formats.
If you can rely on the comma to be there, you can capture the part before it using a negated character class:
^(\d+[A-Z]?)\s+([^,]+?)\s*,\s*(.+?)\s+([A-Z]{2})\s(\d{5})$
Regex demo
Or take the part before the comma that ends on 2 or more uppercase characters, and then match optional non word characters using \W* to get to the first word character after the comma:
^(\d+[A-Z]?)\s+(.*?\b[A-Z]{2,}\b)\W*(.+?)\s+([A-Z]{2})\s(\d{5})$
Regex demo

How to match specific position based on offset number with a specific number of length with regex?

I need to match characters without knowing what characters they will be and the only data I have is an offset number telling me where to start the match and a length number telling me how long the match has to be.
For example:
My string is: "Susan go to the store everyday"
"offset":17
"length":5
Would match "store"
^.{5} This regex matches the length, but is there a way to add an offset rule to this?
My tool doesn't support capture groups.
Assuming your regex tool/language support it, you could use a capture group here:
^.{17}(.{5})
Demo
This would skip the first 17 characters, and then capture the following 5 characters in the first capture group.
Edit:
If your regex tool doesn't have capture groups, you could also use a fixed width lookbehind, e.g.
(?<=^.{17}).{5}
Demo

Regex: grab the string that begins after a certain string and ends when it hits any other character

I am trying to use Regex to grab a substring of a large string.
The overall string has certain text, 'cow/', then any number of characters or spaces that are not digits. The first digit hit is the start of the desired substring I want.
This desired substring consists of only digits and periods, the first character or space seen that is not a digit or period indicates the end of the desired substring.
For example:
'cow/ a12.34 -123'
The desired substring is '12.34'.
So far I have this regex that partially works (I think the '| .' is not entirely correct):
(?<=([A-z]|[0-9])/\s*).?(?=\s[^0-9 |.])
Thanks in advance.
This should be easy to achieve by relying on capturing groups:
cow/[^0-9]*([0-9.]+)
The group will contain the text that you want to extract, in Java group(index), in C# with Groups[index]. Other languages provide similar features.
Don't try to solve everything inside the regular expression, but leverage the power of your runtime :)
Edit after comment on the OP:
Azure Kusto has the extract(regex, captureGroup, text [, typeLiteral]) function to extract groups from regular expression matches:
extract("cow/[^0-9]*([0-9.]+)", 1, "cow/ a12.34 -123") == "12.34";
The argument 1 tells Kusto to extract the first capturing group (the expression inside the parentheses).

Is there a way to capture a pattern, skip a set of random subsequent characters, then continue to capture another pattern using regex?

I have an example of text like
PART I BLABLABLABLALBLA GROUP 2
I need to capture PART I and GROUP 2 using the same regex, skipping the set of characters in the middle.
You can do a capture group for each part you want, and use .* for the middle.
/(PART I).*(GROUP 2)/
and then use $1 and $2 (or the equivalent in your programming language) to get the matched parts.
(Upgraded my comment to an answer, since OP said it worked.)

Detect multiple periods in Regex and kill entire match

I'm trying to detect a price in regex with this:
^\-?[0-9]+(,[0-9]+)?(\.[0-9]+)?
This covers:
12
12.5
12.50
12,500
12,500.00
But if I pass it
12..50 or 12.5.0 or 12.0.
it still returns a match on the 12 . I want it to negate the entire string and return no match at all if there is more than one period in the entire string.
I've been trying to get my head around negative lookaheads for an hour and have searched on Stack Overflow but can't seem to find the right answer. How do I do this?
What you are looking for, is this:
^\d+(,\d{3})*(\.\d{1,2})?$
What it does:
^ Start of Line
\d+ one or more Digits followed by
(,\d{3})* zero, one or more times a , followed by three Digits followed by
(\.\d{1,2})? one or zero . followed by one or two Digits followed by
$ End of Line
This will only match valid Prices. The Comma (,) is not obligatory in this Regex, but it will be matched.
Look here: http://www.regextester.com/?fam=98001
If you work with Prices and want to store them in a Database I recommend saving them as INT. So 1,234,56 becomes 123456 or 1,234 becomes 123400. After you matched the valid price, all you have to do is to remove the ,s, split the Value by the Dot, and fill the Value of [1] with str_pad() (STR_PAD_RIGHT) with Zeros. This makes Calculations easier, in special when you work with Javascript or other different Languages.
Your regex:
^\-?[0-9]+(,[0-9]+)?(\.[0-9]+)?
Note: The regex you provided does not seem to work for 12 (without "."). Since you didn't add a quantifier after \., it tries to match that pattern literally (.).
While there are multiple ways to solve this and the most "correct" answer will depend on your specific requirements, here's a regex that will not match 12..1, but will match 12.1:
(^\-?[0-9]+(?:,[0-9]+)?(?:\.[0-9]+))+
I surrounded the entire regex you provided in a capturing group (...), and added a one or more quantifier + at the end, so that the entire regex will fail if it does not satisfy that pattern.
Also (this may or may not be what you want), I modified the inner groups into non-capturing groups (?: ... ) so that it does not return unnecessary groups.
This site offers a deconstruction of regexes and explains them:
For the regex provided: https://regex101.com/r/EDimzu/2
Unit tests: https://regex101.com/r/EDimzu/2/tests (Note the 12 one's failure for multiple languages).
You can limit it by requiring there is only 0 or 1 periods like this:
^[0-9,]+[\.]{0,1}?[0-9,]+$