price formatting fails to match commas - java

I have this test:
#Test
public void succeedsWhenFormatWithTwoCommas(){
String input = "#,###,###.##";
PriceFormatValidator priceFormatValidator = new PriceFormatValidator();
boolean answer = priceFormatValidator.validate(input);
assertTrue(answer);
}
and it fails when it runs this code:
public boolean validate(String input) {
Pattern pattern = Pattern.compile("^#{1,3}(,?#{3})?(\\.#{0,3})?$");
Matcher matcher = pattern.matcher(input);
boolean isValid = matcher.matches();
return isValid;
}
why is that

Your ^#{1,3}(,?#{3})?(\\.#{0,3})?$ regex only allows 1 or zero ,### inside because (,?#{3})? matches an optional sequence of one or zero , followed with exactly 3 # symbols.
You need to turn the (,?#{3})? part into (,#{3})* to allow zero or more sequences of , + three # symbols.
Use
"^#{1,3}(,#{3})*(\\.#{0,3})?$"
See the regex demo.
The whole pattern will now match the following:
^ - start of string
#{1,3} - one to three #
(,#{3})* - zero or more ,+3 # symbols sequences
(\\.#{0,3})? - an optional . + 0 to 3 # symbols
$ - end of string.
NOTE: The (\\.#{0,3})? at the end allows a trailing .. If you do not want that, change it to (\\.#{1,3})?.
NOTE 2: If you are not using the captured values (those matched with (...) patterns), it is a good idea to change capturing groups into non-capturing ones (i.e. (...) with (?:...)).

You can replece your pattern by:
Pattern pattern = Pattern.compile("^#{1,3}(,?#{3}){1,2}(\\.#{0,3})?$");

Related

Java non-greedy (?) regex to match string

String poolId = "something/something-else/pools[name='test'][scope='lan1']";
String statId = "something/something-else/pools[name='test'][scope='lan1']/stats[base-string='10.10.10.10']";
Pattern pattern = Pattern.compile(".+pools\\[name='.+'\\]\\[scope='.+'\\]$");
What regular expression should be used such that
pattern.matcher(poolId).matches()
returns true whereas
pattern.matcher(statsId).matches()
returns false?
Note that
something/something-else is irrelevant and can be of any length
Both name and scope can have ANY character including any of \, /, [, ] etc
stats[base-string='10.10.10.10'] is an example and there can be anything else after /
I tried to use the non-greedy ? like so .+pools\\[name='.+'\\]\\[scope='.+?'\\]$ but still both matches return true
You can use
.+pools\[name='[^']*'\]\[scope='[^']*'\]$
See the regex demo. Details:
.+ - any one or more chars other than line break chars as many as possible
pools\[name=' - a pools[name='string
[^']* - zero or more chars other than a '
'\]\[scope=' - a '][scope=' string
[^']* - zero or more chars other than a '
'\] - a '] substring
$ - end of string.
In Java:
Pattern pattern = Pattern.compile(".+pools\\[name='[^']*']\\[scope='[^']*']$");
See the Java demo:
//String s = "something/something-else/pools[name='test'][scope='lan1']"; // => Matched!
String s = "something/something-else/pools[name='test'][scope='lan1']/stats[base-string='10.10.10.10']";
Pattern pattern = Pattern.compile(".+pools\\[name='[^']*']\\[scope='[^']*']$");
Matcher matcher = pattern.matcher(s);
if (matcher.find()){
System.out.println("Matched!");
} else {
System.out.println("Not Matched!");
}
// => Not Matched!
Wiktor assumed that your values for name and scope cannot have single quotes in them. Thus the following:
.../pools[name='tes't']
would not match. This is really the only valid assumption to make, as if you can include unescaped single quotes, then what's to stop the value of scope from being (for example) the literal value lan1']/stats[base-string='10.10.10.10? The regex you included in your question has this issue. If you simply must have these values in your code, you need to escape them somehow. Try the following (edit of Wiktor's regex):
.+pools\[name='([^']|\\')*'\]\[scope='([^']|\\')*'\]$

What regex should I use to check a string only has numbers and 2 special characters ( - and , ) in Java?

Scenario: I want to check whether string contains only numbers and 2 predefined special characters, a dash and a comma.
My string contains numbers (0 to 9) and 2 special characters: a dash (-) defines a range and a comma (,) defines a sequence.
Tried attempt :
Tried following regex [0-9+-,]+, but not working as expected.
Possible inputs :
1-5
1,5
1-5,6
1,3,5-10
1-5,6-10
1,3,5-7,8,10
The regex should not accept these types of strings:
-----
1--4
,1,5
5,6,
5,4,-
5,6-
-5,6
Please can any one help me to create regex for above scenario?
You may use
^\d+(?:-\d+)?(?:,\d+(?:-\d+)?)*$
See the regex demo
Regex details:
^ - start of string
\d+ - 1 or more digits
(?:-\d+)? - an optional sequence of - and 1+ digits
(?:,\d+(?:-\d+)?)* - zero or more seuqences of:
, - a comma
\d+(?:-\d+)? - same pattern as described above
$ - end of string.
Change your regex [0-9+-,]+ to [0-9,-]+
final String patternStr = "[0-9,-]+";
final Pattern p = Pattern.compile(patternStr);
String data = "1,3,5-7,8,10";
final Matcher m = p.matcher(data);
if (m.matches()) {
System.out.println("SUCCESS");
}else{
System.out.println("ERROR");
}

Matcher cannot recognize the second group of regular expression in java

I've got a problem when I'm using Matcher for finding a symbol from the group of regular expressions, it cannot recognize the second group .Maybe the code below make it clear :
public void set(String n){
String pat = "(\\d+)[!##$%^&*()_+-=}]";
Pattern r;
r = Pattern.compile(pat);
System.out.println(r);
Matcher m;
m = r.matcher(n);
if (m.find()) {
JOptionPane.showMessageDialog(null,
"Not a correct form", "ERROR_NAME_MATCH", 0);
}else{
name = n;
}
}
After running the code the first group is recognizable but the second one [!##$%^&*()_+-=}] is not.I'm totally sure that the expression is true I've checked it with 'RegexBuddy'. There must be a problem with concatenating two or more groups in one line.
Thank you for your help.
Your regex - (\d+)[!##$%^&*()_+=}-] - matches a sequence of 1+ digits followed with a symbol from the specified set.
You want to test a string and return true if a single character from the specified set is present in the string.
So, just move \d to the character class and certainly move the - to the end of this class:
String pat = "[\\d!##$%^&*()_+=}-]";
^^^
If you need to match a digit or special char, use
String pat = "\\d|[!##$%^&*()_+=}-]";
If you need both irrespective of the order:
String pat = "^(?=\\D*\\d)(?=[^!##$%^&*()_+=}-]*[!##$%^&*()_+=}-])";

Java Regex inconsistent groups

Please Refer to following question on SO:
Java: Regex not matching
My Regex groups are not consistent. My code looks like:
public class RegexTest {
public static void main(String[] args) {
// final String VALUES_REGEX = "^\\{([0-9a-zA-Z\\-\\_\\.]+)(?:,\\s*([0-9a-zA-Z\\-\\_\\.]*))*\\}$";
final String VALUES_REGEX = "\\{([\\w.-]+)(?:, *([\\w.-]+))*\\}";
final Pattern REGEX_PATTERN = Pattern.compile(VALUES_REGEX);
final String values = "{df1_apx.fhh.irtrs.d.rrr, ffd1-afp.farr.d.rrr.asgd, ffd2-afp.farr.d.rrr.asgd}";
final Matcher matcher = REGEX_PATTERN.matcher(values);
if (null != values && matcher.matches()) {
// for (int index=1; index<=matcher.groupCount(); ++index) {
// System.out.println(matcher.group(index));
// }
while (matcher.find()) {
System.out.println(matcher.group());
}
}
}
}
I tried following combinations:
A) Regex as "^\{([0-9a-zA-Z\-\_\.]+)(?:,\s*([0-9a-zA-Z\-\_\.]))\}$" and use groupCount() to iterate. Result:
df1_apx.fhh.irtrs.d.rrr
ffd2-afp.farr.d.rrr.asgd
B) Regex as ^\{([0-9a-zA-Z\-\_\.]+)(?:,\s*([0-9a-zA-Z\-\_\.]))\}$" and use matcher.find(). Result: No result.
C) Regex as "\{([\w.-]+)(?:, ([\w.-]+))\}" and use groupCount() to iterate. Result:
df1_apx.fhh.irtrs.d.rrr
ffd2-afp.farr.d.rrr.asgd
D) Regex as "\{([\w.-]+)(?:, ([\w.-]+))\}" and use matcher.find(). Result: No results.
I never get consistent groups. Expected result here is:
df1_apx.fhh.irtrs.d.rrr
ffd1-afp.farr.d.rrr.asgd
ffd2-afp.farr.d.rrr.asgd
Please let me know, how can I achieve it.
(?<=[{,])\s*(.*?)(?=,|})
You can simply use this and grab the captures.See demo.
https://regex101.com/r/sJ9gM7/33
When you have (#something)* then only the last group is remembered by the regex engine.You wont get all the groups this way.
The problem is that you are trying to make two things at the same time:
you want to validate the string format
you want to extract each items (with an unknow number of items)
So, it's not possible using the matches method, since when you repeat the same capture group previous captures are overwritten by the last.
One possible way is to use the find method to obtain each items and to use the contiguity anchor \G to check the format. \G ensures that the current match immediatly follows the previous or the start of the string:
(?:\\G(?!\\A),\\s*|\\A\\{)([\\w.-]+)(}\\z)?
pattern details:
(?: # two possible begins:
\\G(?!\\A),\\s* # contiguous to a previous match
# (but not at the start of the string)
| # OR
\\A\\{ # the start of the string
)
([\\w.-]+) # an item in the capture group 1
(}\\z)? # the optional capture group 2 to check
# that the end of the string has been reached
So to check the format of the string from start to end all you need is to test if the capture group 2 exists for the last match.

Regex for numeric portion of Java string

I'm trying to write a Java method that will take a string as a parameter and return another string if it matches a pattern, and null otherwise. The pattern:
Starts with a number (1+ digits); then followed by
A colon (":"); then followed by
A single whitespace (" "); then followed by
Any Java string of 1+ characters
Hence, some valid string thats match this pattern:
50: hello
1: d
10938484: 394958558
And some strings that do not match this pattern:
korfed49
: e4949
6
6:
6:sdjjd4
The general skeleton of the method is this:
public String extractNumber(String toMatch) {
// If toMatch matches the pattern, extract the first number
// (everything prior to the colon).
// Else, return null.
}
Here's my best attempt so far, but I know I'm wrong:
public String extractNumber(String toMatch) {
// If toMatch matches the pattern, extract the first number
// (everything prior to the colon).
String regex = "???";
if(toMatch.matches(regex))
return toMatch.substring(0, toMatch.indexOf(":"));
// Else, return null.
return null;
}
Thanks in advance.
Your description is spot on, now it just needs to be translated to a regex:
^ # Starts
\d+ # with a number (1+ digits); then followed by
: # A colon (":"); then followed by
# A single whitespace (" "); then followed by
\w+ # Any word character, one one more times
$ # (followed by the end of input)
Giving, in a Java string:
"^\\d+: \\w+$"
You also want to capture the numbers: put parentheses around \d+, use a Matcher, and capture group 1 if there is a match:
private static final Pattern PATTERN = Pattern.compile("^(\\d+): \\w+$");
// ...
public String extractNumber(String toMatch) {
Matcher m = PATTERN.matcher(toMatch);
return m.find() ? m.group(1) : null;
}
Note: in Java, \w only matches ASCII characters and digits (this is not the case for .NET languages for instance) and it will also match an underscore. If you don't want the underscore, you can use (Java specific syntax):
[\w&&[^_]]
instead of \w for the last part of the regex, giving:
"^(\\d+): [\\w&&[^_]]+$"
Try using the following: \d+: \w+

Categories