how to get a number between two characters? - regex

I have this string:
String values="[52,52,73,52],[23,32],[40]";
How to only get the number 40?
I'm trying this pattern "\\[^[0-9]*$\\]", I've had no luck.
Can someone provide me with the appropriate pattern?

There is no need to use ^
The correct regex here is \\[([0-9]+)\\]$
If you are sure of the single number inside the [], this simple regex would do
\\[(\d+)\\]

Your could update your pattern to use a capturing group and a quantifier + after the character class and omit the ^ anchor to assert the start of the string.
Change the anchor to assert the end of string $ to the end of the pattern:
\\[([0-9]+)\\]$
^ ^^
Regex demo | Java demo
For example:
String regex = "\\[([0-9]+)\\]$";
String string = "[52,52,73,52],[23,32],[40]";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(string);
if(matcher.find()) {
System.out.println(matcher.group(1)); // 40
}

Given that you appear to be using Java, I recommend taking advantage of String#split here:
String values = "[52,52,73,52],[23,32],[40]";
String[] parts = values.split("(?<=\\]),(?=\\[)");
String[][] contents = new String[parts.length][];
for (int i=0; i < parts.length; ++i) {
contents[i] = parts[i].replaceAll("[\\[\\]]", "").split(",");
}
// now access any element at any position, e.g.
String forty = contents[2][0];
System.out.println(forty);
What the above snippet generates is a jagged 2D Java String array, where the first index corresponds to the array in the initial CSV, and the second index corresponds to the element inside that array.

Why not just use String.substring if you need the content between the last [ and last ]:
String values = "[52,52,73,52],[23,32],[40]";
String wanted = values.substring(values.lastIndexOf('[')+1, values.lastIndexOf(']'));

Related

DART Conditional find and replace using Regex

I have a string that sometimes contains a certain substring at the end and sometimes does not. When the string is present I want to update its value. When it is absent I want to add it at the end of the existing string.
For example:
int _newCount = 7;
_myString = 'The count is: COUNT=1;'
_myString2 = 'The count is: '
_rRuleString.replaceAllMapped(RegExp('COUNT=(.*?)\;'), (match) {
//if there is a match (like in _myString) update the count to value of _newCount
//if there is no match (like in _myString2) add COUNT=1; to the string
}
I have tried using a return of:
return "${match.group(1).isEmpty ? _myString + ;COUNT=1;' : 'COUNT=$_newCount;'}";
But it is not working.
Note that replaceAllMatched will only perform a replacement if there is a match, else, there will be no replacement (insertion is still a replacement of an empty string with some string).
Your expected matches are always at the end of the string, and you may leverage this in your current code. You need a regex that optionally matches COUNT= and then some text up to the first ; including the char and then checks if the current position is the end of string.
Then, just follow the logic: if Group 1 is matched, set the new count value, else, add the COUNT=1; string:
The regex is
(COUNT=[^;]*;)?$
See the regex demo.
Details
(COUNT=[^;]*;)? - an optional group 1: COUNT=, any 0 or more chars other than ; and then a ;
$ - end of string.
Dart code:
_myString.replaceFirstMapped(RegExp(r'(COUNT=[^;]*;)?$'), (match) {
return match.group(0).isEmpty ? "COUNT=1;" : "COUNT=$_newCount;" ; }
)
Note the use of replaceFirstMatched, you need to replace only the first match.

Regular expression to match all digits of unknown length except the last 4 digits

There is a number with unknown length and the idea is to build a regular expression which matches all digits except last 4 digits.
I have tried a lot to achieve this but no luck yet.
Currently I have this regex: "^(\d*)\d{0}\d{0}\d{0}\d{0}.*$"
Input: 123456789089775
Expected output: XXXXXXXXXXX9775
which I am using as follows(and this doesn't work):
String accountNumber ="123456789089775";
String pattern = "^(\\d*)\\d{1}\\d{1}\\d{1}\\d{1}.*$";
String result = accountNumber.replaceAll(pattern, "X");
Please suggest how I should approach this problem or give me the solution.
In this case my whole point is to negate the regex : "\d{4}$"
You may use
\G\d(?=\d{4,}$)
See the regex demo.
Details
\G - start of string or end of the previous match
\d - a digit
(?=\d{4,}$) - a positive lookahead that requires 4 or more digits up to the end of the string immediately to the right of the current location.
Java demo:
String accountNumber ="123456789089775";
String pattern = "\\G\\d(?=\\d{4,}$)"; // Or \\G.(?=.{4,}$)
String result = accountNumber.replaceAll(pattern, "X");
System.out.println(result); // => XXXXXXXXXXX9775
still not allowed to comment as I don't have that "50 rep" yet but DDeMartini's answer would swallow prefixed non-number-accounts as "^(.*)" would match stuff like abcdef1234 as well - stick to your \d-syntax
"^(\\d+)(\\d{4}$)"
seems to work fine and demands numbers (minimum length 6 chars). Tested it like
public class AccountNumberPadder {
private static final Pattern LAST_FOUR_DIGITS = Pattern.compile("^(\\d+)(\\d{4})");
public static void main(String[] args) {
String[] accountNumbers = new String[] { "123456789089775", "999775", "1234567890897" };
for (String accountNumber : accountNumbers) {
Matcher m = LAST_FOUR_DIGITS.matcher(accountNumber);
if (m.find()) {
System.out.println(paddIt(accountNumber, m));
} else {
throw new RuntimeException(String.format("Whooaaa - don't work for %s", accountNumber));
}
}
}
public static String paddIt(String input, Matcher m) {
StringBuilder b = new StringBuilder();
for (int i = 0; i < m.group(1).length(); i++) {
b.append("X");
}
return input.replace(m.group(1), b.toString());
}
}
Try:
String pattern = "^(.*)[0-9]{4}$";
Addendum after comment: A refactor to only match full numerics could look like this:
String pattern = "^([0-9]+)[0-9]{4}$";

Regular expression to match n times in which n is not fixed

The pattern I want to match is a sequence of length n where n is right before the sequence.
For example, when the input is "1aaaaa", I want to match the single character "a", as the first number specifies only 1 character is matched.
Similar, when the input is "2aaaaa", I want to match the first two characters "aa", but not the rest, as the number 2 specifies two characters will be matched.
I understand a{1} and a{2} will match "a" one or two times. But how to match a{n} in which n is not fixed?
Is it possible to do this type of match using regular expressions?
This will work for repeating numbers.
import re
a="1aaa2bbbbb1cccccccc4dddddddddddd"
for b in re.findall(r'\d[a-z]+', a):
print b[int(b[0])+1:int(b[0])+1+int(b[0])]
Output:
a
bb
c
dddd
Though I have done in Java, it will help you get going in your program.
Here you can select the first letter as sub-string from the given input string and use it in your regex to match the string accordingly.
public class DynamicRegex {
public static void main(String args[]){
Scanner scan = new Scanner(System.in);
System.out.println("Enter a string: ");
String str = scan.nextLine();
String testStr = str.substring(0, 1); //Get the first character from the string using sub-string.
String pattern = "a{"+ testStr +"}"; //Use the sub-string in your regex as length of the string to match.
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(str);
if(m.find()){
System.out.println(m.group());
}
}
}

Java regex all characters except last

I want to place a dash after every letter but my regex place a dash at the end too. How can I improve my regex?
String outputS = dnaString.replaceAll("(.{1})", "$1-");
(.)(?!$)
You can use this.Replace by $1.See demo.
https://regex101.com/r/gT6vU5/11
(?!$) uses negative lookahead to state that do not capture a character which is at end of string.
Without regex (that is faster):
String[] nucleotides = dnaString.split("");
String outputS;
int seqLength = nucleotides.length;
if (seqLength > 1) {
StringBuilder sb = new StringBuilder();
sb.append(nucleotides[0]);
for (int i = 1; i < seqLength; i++) {
sb.append("-");
sb.append(nucleotides[i]);
}
outputS = sb.toString();
} else {
outputS = dnaString;
}
I know this is an old question, but for completeness and future reference I would like to add this answer.
In Java 8 you can also use:
String.join("-",dnaString.toCharArray());
Explanation:
String.join(delimiter,objects...);
String.join(delimiter,array);
String.join(delimiter,Iterable);
These are used to join all objects to a single string with the delimiter as separator.
dnaString.toCharArray();
This is a method to get a String as an char array.
This replaces all special characters with underscore '_' except the last occurence of a special character in the string.
String name = "one-of-the dummy$ string:i.txt"; // input
name = name.replaceAll("[^a-zA-Z0-9](?=.*[^a-zA-Z0-9])", "_");
System.out.println(name);
//input: one-of-the dummy$ string:i.txt
//output: one_of_the_dummy__string_i.txt
This
(.)\B
doesn't match the last char.
See https://regex101.com/r/p0Z0zA/1
So, in your case, should be:
String outputS = dnaString.replaceAll("(.{1})\\B", "$1-");
Credits to pigreco.

Using RegEx split the string

I have a string like '[1]-[2]-[3],[4]-[5],[6,7,8],[9]' or '[Computers]-[Apple]-[Laptop],[Cables]-[Cables,Connectors],[Adapters]', I'd like the Pattern to get the list result, but don't know how to figure out the pattern. Basically the comma is the split, but [6,7,8] itself contains the comma as well.
the string: [1]-[2]-[3],[4]-[5],[6,7,8],[9]
the result:
[1]-[2]-[3]
[4]-[5]
[6,7,8]
[9]
or
the string: [Computers]-[Apple]-[Laptop],[Cables]-[Cables,Connectors],[Adapters]
the result:
[Computers]-[Apple]-[Laptop]
[Cables]-[Cables,Connectors]
[Adapters]
,(?=\[)
This pattern splits on any comma that is followed by a bracket, but keeps the bracket within the result text.
The (?=*stuff*) is known as a "lookahead assertion". It acts as a condition for the match but is not itself part of the match.
In C# code:
String inputstring = "[Computers]-[Apple]-[Laptop],[Cables]-[Cables,Connectors],[Adapters]";
foreach(String s in Regex.Split(inputstring, #",(?=\[)"))
System.Console.Out.WriteLine(s);
In Java code:
String inputstring = "[Computers]-[Apple]-[Laptop],[Cables]-[Cables,Connectors],[Adapters]";
Pattern p = Pattern.compile(",(?=\\[)"));
for(String s : p.split(inputstring))
System.out.println(s);
Either produces:
[Computers]-[Apple]-[Laptop]
[Cables]-[Cables,Connectors]
[Adapters]
Although I believe the best approach here is to use split (as presented by #j__m's answer), here's an approach that uses matching rather than splitting.
Regex:
(\[.*?\](?!-))
Example usage:
String input = "[Computers]-[Apple]-[Laptop],[Cables]-[Cables,Connectors],[Adapters]";
Pattern p = Pattern.compile("(\\[.*?\\](?!-))");
Matcher m = p.matcher(input);
while (m.find()) {
System.out.println(m.group(1));
}
Resulting output:
[Computers]-[Apple]-[Laptop]
[Cables]-[Cables,Connectors]
[Adapters]
An answer that doesn't use regular expressions (if that's worth something in ease of understanding what's going on) is:
substitute "]#[" for "],["
split on "#"