Regex : Digits followed by only one character - java

I'm trying to create a regex that will allow only digits followed by only one character after every digit within a Textfield
Regex that needs to match - \d*\+{1}
Regex in case it does not match - [^\d*\+){1}] will replace with "" (removes everything else)
final String regexFinalInteger = "\\d*\\+{1}";
numberElements.textProperty().addListener((observable, oldValueE, newValueE) -> {
if (!newValueE.matches(regexFinalInteger)) {
numberElements.setText(newValueE.replaceAll("[^\\d*\\+){1}]", ""));
}
});
I will expect an output of 122+1+3 but the actual output can be 1++2+++4+123 (multiple +)

If I understood correctly, you want to replace multiple +s with only one.
I believe this would enable what you're looking for:
String regex = "[+](?=[+])";
String text = "122+1+3";
assertEquals("122+1+3", text.replaceAll(regex, ""));
text = "1++2+++4+123";
assertEquals("1+2+4+123", text.replaceAll(regex, ""));
That is my first Java program, I'm sorry if it offends someone.

Related

Partially mask data of a group of number using regex

I would like to partially mask data using regex. Here is the input :
123-12345-1234567
And here is what I'd like as output :
1**-*****-*****67
I figure out how to replace for the last group but I don't know to do for the rest of the data.
String s = "123-12345-1234567";
System.out.println(s.replaceAll("\\d(?=\\d{2})", "*")); // output is *23-***45-*****67
Also, I'd like to use only regex because I have different type of data, so different type of mask. I don't want to create functions for each type of data.
For example :
AAAAAAAAA // becomes ********AA
12334567 // becomes 123******
Thanks for your help !
We can use the following regex replacement approach:
String input = "123-12345-1234567";
String output = input.substring(0, 1) +
input.substring(1, input.length()-2).replaceAll("\\d", "*") +
input.substring(input.length()-2);
System.out.println(output); // 1**-*****-*****67
Here we concatenate together the first digit, followed by the middle portion with all digits replaced by *, along with the final two digits.
Edit: A pure regex solution, which, however, is more lines of code than the above and might be less performant.
String input = "123-12345-1234567";
String pattern = "^(\\d)(.*)(\\d{2})$";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(input);
if (m.find()) {
String output = m.group(1) + m.group(2).replaceAll("\\d", "*") + m.group(3);
System.out.println(output); // 1**-*****-*****67
}
Java supports a fixed quantifier in a lookbehind, so what you might do is use a pattern with an alternation to account for the different scenario's if you must use a regex only.
Using the lookarounds you can select a single character to be replaced by *
Note that this is hard to maintain, and it would be a better option to write separate functions for the different data formats using separate patterns or string functions (perhaps accompanied by unit tests)
(?<=^\d{3,7})\d(?=\d*$)|(?<=^[A-Z]{0,6})[A-Z](?=[A-Z]*$)|\d(?<=^\d{2,3})(?=\d?-\d{5}-\d{7}$)|\d(?<=^\d{3}-\d{1,5}(?:-\d{1,5})?)
The separate parts match:
(?<=^\d{3,7})\d(?=\d*$) Match a digit asserting 3-7 digits to the left and only digits to the right
| Or
(?<=^[A-Z]{0,6})[A-Z](?=[A-Z]*$) Match A-Z asserting 0-6 chars to the left and only chars A-Z to the right
| Or
\d(?<=^\d{2,3})(?=\d?-\d{5}-\d{7}$) Match a digit asserting 2-3 digits to the left and optional digit, - with 5 digits and - with 7 digits to the right
| Or
\d(?<=^\d{3}-\d{1,5}(?:-\d{1,5})?) Match a digit asserting 3 digits to the left followed - and 1-5 digits and optionally - with 1-5 digits
Regex demo | Java demo
String regex = "(?<=^\\d{3,7})\\d(?=\\d*$)|(?<=^[A-Z]{0,6})[A-Z](?=[A-Z]*$)|\\d(?<=^\\d{2,3})(?=\\d?-\\d{5}-\\d{7}$)|\\d(?<=^\\d{3}-\\d{1,5}(?:-\\d{1,5})?)";
String s1 = "123-12345-1234567";
String s2 = "AAAAAAAAA";
String s3 = "12334567";
System.out.println(s1.replaceAll(regex, "*"));
System.out.println(s2.replaceAll(regex, "*"));
System.out.println(s3.replaceAll(regex, "*"));
Output
1**-*****-*****67
*******AA
123*****
public static void main(String[] args) {
System.out.println("123-12345-1234567".replaceAll("(?<=.{1,})\\d(?=.{3,})", "*"));
System.out.println("AAAAAAAAA".replaceAll(".(?=.{2,})", "*"));
System.out.println("12334567".replaceAll("(?<=.{3,}).", "*"));
}
output:
1**-*****-*****67
*******AA
123*****

Regex expression is not working correctly

I am trying to find in a string in which numbers are formatted as "4.97", but if they are smaller than 1, they are in the format .97, .80 etc. I want to find these kind of substrings in the String and replace them so that they would start with a 0.
It's working for the string
String str = "Rate is : .97";
Result : "Rate is : 0.97"
But not for the string:
String str = "Rate is : .97 . XXXXXXXXX do you want . to perform another calculation . ";
String str = "Rate is : .97 . XXXXXXXXX do you want . 87 to perform another calculation . ";
String pattern = "(.*\\D)(.\\d\\d.*)";
System.out.println(str.matches("(.*\\D)(.\\d\\d.*)"));
str = str.replaceAll(pattern, "$10$2");
Why is this happening?
In your second example, the .* after the last \\d will match any character except a newline which will match the rest of the string.
You might do the replacement without a capturing group using a negative lookbehind (?<!\S) to check if what is on the left is not a non whitespace char.
(?<!\S)\.[0-9]
In the replacement use a zero followed by the full match.
Regex demo | Java demo
String str = "Rate is : .97 . XXXXXXXXX do you want . 87 to perform another calculation . ";
String pattern = "(?<!\\S)\\.[0-9]";
System.out.println(str.replaceAll(pattern, "0$0"));
Output
Rate is : 0.97 . XXXXXXXXX do you want . 87 to perform another calculation .
If there should be a non digit before, you could make use of a positive lookbehind
(?<=\D)\.[0-9]
Regex demo
In Java
String regex = "(?<=\\D)\\.[0-9]";
It looks like you need to add some lazy matching to your regex.
? means it will attempt to match as few times as possible, in this case it's to only pick up the first number and not go onto the second.
^(.*?\D)(.\d\d.*?)
You can see this regex work here, with a more complete explanation.
I have also added the ^ start of string matcher so to make sure only one match it created and not repeated onto the second.
First of all, your regex pattern seems to be wrong. I think you can just use:
(\D)(\.\d+)
Find a character that is not a digit, followed by a dot and at least one digit.
Second, for replacing, you could use more low-level features, such as:
String str = "Rate is : .97 . XXXXXXXXX do you want . 87 to perform another calculation . ";
final Pattern regex = Pattern.compile("(\\D)(\\.\\d+)");
final Matcher m = regex.matcher(str);
if (m.find()) {
str = m.replaceFirst(m.group(1) + "0" + m.group(2));
}
System.out.println(str);
But of course, this works too:
str = str.replaceAll("(\\D)(\\.\\d+)", "$10$2");
You can do a positive lookahead so that way you also catch whitespaces between . and the number.
(.(?=.\d)|(\d+))+
would give you
Then in your code you can do whatever operation on group 1(blue) and group 2(red) as you wish.

Regex Java when we have specific text upto a pattern

As i haven't much worked on regex, can someone help me out in getting the answer for below thing:
(1)I want to remove a text say Element
(2)It may of may not followed by delimiter say pipe(||)
I tried below thing, but it is not working in the way i want:
String str = "String:abc||Element:abc||Value:abc"; // Sample text 1
String str1 = "String:abc||Element:abc"; // Sample text 2
System.out.println(str.replaceFirst("Element.*\\||", ""));
System.out.println(str1.replaceFirst("Element.*\\||", ""));
Required output in above cases:
String:abc||Value:abc //for the first case
String:abc //for the second case
Assuming that you can decide to give another value to the original pattern which is Element in this case, you can use Pattern.quote to escape it as below:
String str = "String:abc||Element:abc||Value:abc"; // Sample text 1
String str1 = "String:abc||Element:abc"; // Sample text 2
String originalPattern = "Element";
String pattern = String.format("\\|{2}%s[^\\|]+", Pattern.quote(originalPattern));
System.out.println(str.replaceFirst(pattern, ""));
System.out.println(str1.replaceFirst(pattern, ""));
Your patter is then generic and its value is String.format("\\|{2}%s[^\\|]+", Pattern.quote(originalPattern))
Output:
String:abc||Value:abc
String:abc
You put the escape wrong. It should be:
Element(.*?\|\||.*$)
Put the escape on each pipe, and use ? for non greedy Regex so you only replace just enough string, not everything.
String text = "String:abc||Element:abc||Value:abc";
text = text.replaceAll("\\belement\\b", "");
you might need to use replace all this will replace all element from your string here i am using '\b' word boundary in java regular expression in between the words

java regex to match multiple new line characters up to character

I have the following text string, consisting of a block of text followed by two or more
new line characters (\n maybe \r) followed by another block of text,etc like this
multiple line text
(two or more new line characters)
multiple line tex
(two or more new line characters)
I would like to break this string into as many substrings as the number of blocks of text using the new lines as the breaking boundary.
I tried
public static int indexOf(Pattern pattern, String s) {
Matcher matcher = pattern.matcher(s);
return matcher.find() ? matcher.start() : -1;
}
pStart[i-1] = start + indexOf(Pattern.compile("[\\n\\n]+"), text.substring(start));
but it doesnt work.
Is there a better idea to handle it?
You need to understand that [\\n\\n] means only one new line character \n since it is inside character class. Inside character class only one of the listed characters are matched.
You can use:
\\n{2}
instead to match new newline characters.
Any easy way is to use the String Split Function with a Regex:
String sampleText = new String("first\nsecond\n\r");
String [] blocks = sampleText.split("\n{1,}[\r]?");
The above assumes '1 or more \n' and optionally '1 \r'.
You can change the regex to '\n{2,}[\r]?' for two or more '\n' depending on what you want.
Oracle Java 6 String Split Docs
Cheers!

Error when splitting a string in java

I am trying to split a string according to a certain set of delimiters.
My delimiters are: ,"():;.!? single spaces or multiple spaces.
This is the code i'm currently using,
String[] arrayOfWords= inputString.split("[\\s{2,}\\,\"\\(\\)\\:\\;\\.\\!\\?-]+");
which works fine for most cases but i'm have a problem when the the first word is surrounded by quotation marks. For example
String inputString = "\"Word\" some more text.";
Is giving me this output
arrayOfWords[0] = ""
arrayOfWords[0] = "Word"
arrayOfWords[1] = "some"
arrayOfWords[2] = "more"
arrayOfWords[3] = "text"
I want the output to give me an array with
arrayOfWords[0] = "Word"
arrayOfWords[1] = "some"
arrayOfWords[2] = "more"
arrayOfWords[3] = "text"
This code has been working fine when quotation marks are used in the middle of the sentence, I'm not sure what the trouble is when it's at the beginning.
EDIT: I just realized I have same problem when any of the delimiters are used as the first character of the string
Unfortunately you wont be able to remove this empty first element using only split. You should probably remove first elements from your string that match your delimiters and split after it. Also your regex seems to be incorrect because
by adding {2,} inside [...] you are in making { 2 , and } characters delimiters,
you don't need to escape rest of your delimiters (note that you don't have to escape - only because it is at end of character class [] so he cant be used as range operator).
Try maybe this way
String regexDelimiters = "[\\s,\"():;.!?\\-]+";
String inputString = "\"Word\" some more text.";
String[] arrayOfWords = inputString.replaceAll(
"^" + regexDelimiters,"").split(regexDelimiters);
for (String s : arrayOfWords)
System.out.println("'" + s + "'");
output:
'Word'
'some'
'more'
'text'
A delimiter is interpreted as separating the strings on either side of it, thus the empty string on its left is added to the result as well as the string to its right ("Word"). To prevent this, you should first strip any leading delimiters, as described here:
How to prevent java.lang.String.split() from creating a leading empty string?
So in short form you would have:
String delim = "[\\s,\"():;.!?\\-]+";
String[] arrayOfWords = inputString.replaceFirst("^" + delim, "").split(delim);
Edit: Looking at Pshemo's answer, I realize he is correct regarding your regex. Inside the brackets it's unnecessary to specify the number of space characters, as they will be caught be the + operator.

Categories

Resources