how to solve adding with REGEX - regex

i want to get math equation only with addition such as 1+2+3 and return its result. i have the following code, and the problem is that it doesn't deal with doubles (i cant write 2.2+3.4)
I tried to change the regex expression to ([\+-]?\d+.\d+)([\+-])(-?(\d+.\d+)) and now it doesnt deal with integers (i cant write 2+4). what should be the correct regex expression to deal with doubles and integers? thanx
the code:
regEx = new Regex(#"([\+-]?\d+)([\+-])(-?(\d+))");
m = regEx.Match(Expression, 0);
while (m.Success)
{
double result;
switch (m.Groups[2].Value)
{
case "+":
result = Convert.ToDouble(m.Groups[1].Value) + Convert.ToDouble(m.Groups[3].Value);
if ((result < 0) || (m.Index == 0)) Expression = regEx.Replace(Expression, DoubleToString(result), 1);
else Expression = regEx.Replace(Expression, "+" + result, 1);
m = regEx.Match(Expression);
continue;
case "-":
result = Convert.ToDouble(m.Groups[1].Value) - Convert.ToDouble(m.Groups[3].Value);
if ((result < 0) || (m.Index == 0)) Expression = regEx.Replace(Expression, DoubleToString(result), 1);
else Expression = regEx.Replace(Expression, "+" + result, 1);
m = regEx.Match(Expression);
continue;
}
}
if (Expression.StartsWith("--")) Expression = Expression.Substring(2);
return Expression;
}

As the comments have stated, RegEx is not a good solution to this problem. You would be much better off with either a simple split statement (if you only want to support the + and - operators), or an actual parser (if you want to support actual mathematical expressions).
But, for the sake of explaining some RegEx, your problem is that \d+.\d+ matches "one or more digits, followed by any character, followed by one or more digits." If you gave it an integer greater than 99, it would work, since you're matching . (any character) and not \. (specifically the dot character).
A simpler version would be [\d\.]+, which matches one-or-more digits-or-dots. The problems is that it allows multiple dots, so 8.8.8.8 is a valid match. So what you really want is \d+\.?\d*, which matches one-or-more digits, one-or-zero dots, and zero-or-more digits. Thus 2, 2., and 2.05 are all valid matches.

Related

Regex: Find a word that consists of certain characters

I have a list of dictionary words, I would like to find any word that consists of (some or all) certain characters of a source word in any order :
For Example:
Characters (source word) to look for : stainless
Found Words : stainless, stain, net, ten, less, sail, sale, tale, tales, ants, etc.
Also if a letter is found once in the source word it can't be repeated in the found word
Unacceptable words to find : tent (t is repeated), tall (l is repeated) , etc.
Acceptable words to find : less (s is already repeated in the source word), etc.
You could take this approach:
Match any sequence of characters that are in the search word, requiring that the match is a word (word-boundaries)
Prohibit that a certain character occurs more often than it is present in the search word, using a negative look-ahead. Do this for every character that is in the search word.
For the given example the regular expression would be:
(?!(\S*s){4}|(\S*t){2}|(\S*a){2}|(\S*i){2}|(\S*n){2}|(\S*l){2}|(\S*e){2})\b[stainless]+\b
The biggest part of the pattern deals with the negative look-ahead. For example:
(\S*s){4} would match four times an 's' in a single word.
(?! | ) places these patterns as different options in a negative look-ahead so that none of them should match.
Automation
It is clear that making such a regular expression for a given word needs some work, so that is where you could use some automation. Notepad++ cannot help with that, but in a programming environment it is possible. Here is a little snippet in JavaScript that will give you the regular expression that corresponds to a given search word:
function regClassEscape(s) {
// Escape "[" and "^" and "-":
return s.replace(/[\]^-]/g, "\\$&");
}
function buildRegex(searchWord) {
// get frequency of each letter:
let freq = {};
for (let ch of searchWord) {
ch = regClassEscape(ch);
freq[ch] = (freq[ch] ?? 0) + 1;
}
// Produce negative options (too many occurrences)
const forbidden = Object.entries(freq).map(([ch, count]) =>
"(\\S*[" + ch + "]){" + (count + 1) + "}"
).join("|");
// Produce character set
const allowed = Object.keys(freq).join("");
return "(?!" + forbidden + ")\\b[" + allowed + "]+\\b";
}
// I/O management
const [input, output] = document.querySelectorAll("input,div");
input.addEventListener("input", refresh);
function refresh() {
if (/\s/.test(input.value)) {
output.textContent = "Input should have no white space!";
} else {
output.textContent = buildRegex(input.value);
}
}
refresh();
input { width: 100% }
Search word:<br>
<input value="stainless">
Regular expression:
<div></div>

Regular expression: Numeric + alphanum + special characters Only

I am trying to build a regular expression that can find patterns that MUST contain both numeric and alphanumeric values along side special characters.
I found an answer that deals with this type of regular expressions but without the special characters.
How can I include the special characters including: ^$=()_"'[\# in the Regular expression?
^([0-9]+[a-zA-Z]+|[a-zA-Z]+[0-9]+)[0-9a-zA-Z]*$
can you explain it a little please ?
Regex tester : http://regexlib.com/RETester.aspx
Thank you.
AS a solution I found this regular expression: ^(?=.*\d)(?=.*[a-zA-Z]).{4,8}$
Maybe it can help you.
Why so complicated !?
enum { numeric = 1; alpha = 2, special = 4; }
bool check(const std::string& s) {
for(std::string::size_type i = 0; i < s.size; ++i) {
if(is_numeric(s[i])) result |= numeric;
if(is_alpha(s[i])) result |= alpha;
if(is_special(s[i])) result |= special;
if(result == numeric | alpha | special)
return true;
}
return false;
}
A little more typing but less brain damage
Your regex is formed of two parts, both must capture a complete line as they're between start-of-line (^) and end-of-line ($):
([0-9]+[a-zA-Z]+|[a-zA-Z]+[0-9]+)
This is formed of two regexs or'd (|) together. The first regex is one or more numbers ([0-9]+) followed by one or more letters ([a-zA-Z]+). This regex is or'd with the opposite case regex: one or more letters followed by one or more numbers.
The second group says that the above is followed by a regex zero or more letters or numbers ([0-9a-zA-Z]*)

Regex for parenthesis (JavaScript)

This is the regexp I created so far:
\((.+?)\)
This is my test string: (2+2) + (2+3*(2+3))
The matches I get are:
(2+2)
And
(2+3*(2+3)
I want my matches to be:
(2+2)
And
(2+3*(2+3))
How should I modify my regular expression?
You cannot parse parentesized expressions with regular expression.
There is a mathematical proof that regular expressions can't do this.
Parenthesized expressions are a context-free grammar, and can thus be recognized by pushdown automata (stack-machines).
You can, anyway, define a regular expression that will work on any expression with less than N parentheses, with an arbitrary finite N (even though the expression will get complex).
You just need to acknowledge that your parentheses might contain another arbitrary number of parenteses.
\(([^()]+(\([^)]+\)[^)]*)*)\)
It works like this:
\(([^()]+ matches an open parenthesis, follwed by whatever is not a parenthesis;
(\([^)]+\)[^)]*)* optionally, there may be another group, formed by an open parenthesis, with something inside it, followed by a matching closing parenthesis. Some other non-parenthesis character may follow. This can be repeated an arbitrary amount of times. Anyway, at last, there must be
)\) another closed parenthesis, which matches with the first one.
This should work for nesting depth 2. If you want nesting depth 3, you have to further recurse, allowing each of the groups I described at point (2) to have a nested parenthesized group.
Things will get much easier if you use a stack. Such as:
foundMatches = [];
mStack = [];
start = RegExp("\\(");
mid = RegExp("[^()]*[()]?");
idx = 0;
while ((idx = input.search(start.substr(idx))) != -1) {
mStack.push(idx);
//Start a search
nidx = input.substr(idx + 1).search(mid);
while (nidx != -1 && idx + nidx < input.length) {
idx += nidx;
match = input.substr(idx).match(mid);
match = match[0].substr(-1);
if (match == "(") {
mStack.push(idx);
} else if (mStack.length == 1) {
break;
}
nidx = input.substr(idx + 1).search(mid);
}
//Check the result
if (nidx != -1 && idx + nidx < input.length) {
//idx+nidx is the index of the last ")"
idx += nidx;
//The stack contains the index of the first "("
startIdx = mStack.pop();
foundMatches.push(input.substr(startIdx, idx + 1 - startIdx));
}
idx += 1;
}
How about you parse it yourself using a loop without the help of regex?
Here is one simple way:
You would have to have a variable, say "level", which keeps track of how many open parentheses you have come across so far (initialize it with a 0).
You would also need a string buffer to contain each of your matches ( e.g. (2+2) or (2+3 * (2+3)) ) .
Finally, you would need somewhere you can dump the contents of your buffer into whenever you finish reading a match.
As you read the string character by character, you would increment level by 1 when you come across "(", and decrement by 1 when you come across ")". You would then put the character into the buffer.
When you come across ")" AND the level happens to hit 0, that is when you know you have a match. This is when you would dump the contents of the buffer and continue.
This method assumes that whenever you have a "(" there will always be a corresponding ")" in the input string. This method will handle arbitrary number of parentheses.

How to use regular expressions to extract 3-tuple values from a string

I am trying to extract n 3-tuples (Si, Pi, Vi) from a string.
The string contains at least one such 3-tuple.
Pi and Vi are not mandatory.
SomeTextxyz#S1((property(P1)val(V1))#S2((property(P2)val(V2))#S3
|----------1-------------|----------2-------------|-- n
The desired output would be:
Si,Pi,Vi.
So for n occurrences in the string the output should look like this:
[S1,P1,V1] [S2,P2,V2] ... [Sn-1,Pn-1,Vn-1] (without the brackets)
Example
The input string could be something like this:
MyCarGarage#Mustang((property(PS)val(500))#Porsche((property(PS)val(425‌​)).
Once processed the output should be:
Mustang,PS,500 Porsche,PS,425
Is there an efficient way to extract those 3-tuples using a regular expression
(e.g. using C++ and std::regex) and what would it look like?
#(.*?)\(\(property\((.*?)\)val\((.*?)\)\) should do the trick.
example at http://regex101.com/r/bD1rY2
# # Matches the # symbol
(.*?) # Captures everything until it encounters the next part (ungreedy wildcard)
\(\(property\( # Matches the string "((property(" the backslashes escape the parenthesis
(.*?) # Same as the one above
\)val\( # Matches the string ")val("
(.*?) # Same as the one above
\)\) # Matches the string "))"
How you should implement this in C++ i don't know but that is the easy part :)
http://ideone.com/S7UQpA
I used C's <regex.h> instead of std::regex because std::regex isn't implemented in g++ (which is what IDEONE uses). The regular expression I used:
" In C(++)? regexes are strings.
# Literal match
([^(#]+) As many non-#, non-( characters as possible. This is group 1
( Start another group (group 2)
\\(\\(property\\( Yet more literal matching
([^)]+) As many non-) characters as possible. Group 3.
\\)val\\( Literal again
([^)]+) As many non-) characters as possible. Group 4.
\\)\\) Literal parentheses
) Close group 2
? Group 2 optional
" Close Regex
And some c++:
int getMatches(char* haystack, item** items){
first, calculate the length of the string (we'll use that later) and the number of # found in the string (the maximum number of matches)
int l = -1, ats = 0;
while (haystack[++l])
if (haystack[l] == '#')
ats++;
malloc a large enough array.
*items = (item*) malloc(ats * sizeof(item));
item* arr = *items;
Make a regex needle to find. REGEX is #defined elsewhere.
regex_t needle;
regcomp(&needle, REGEX, REG_ICASE|REG_EXTENDED);
regmatch_t match[5];
ret will hold the return value (0 for "found a match", but there are other errors you may want to be catching here). x will be used to count the found matches.
int ret;
int x = -1;
Loop over matches (ret will be zero if a match is found).
while (!(ret = regexec(&needle, haystack, 5, match,0))){
++x;
Get the name from match1
int bufsize = match[1].rm_eo-match[1].rm_so + 1;
arr[x].name = (char *) malloc(bufsize);
strncpy(arr[x].name, &(haystack[match[1].rm_so]), bufsize - 1);
arr[x].name[bufsize-1]=0x0;
Check to make sure the property (match[3]) and the value (match[4]) were found.
if (!(match[3].rm_so > l || match[3].rm_so<0 || match[3].rm_eo > l || match[3].rm_so< 0
|| match[4].rm_so > l || match[4].rm_so<0 || match[4].rm_eo > l || match[4].rm_so< 0)){
Get the property from match[3].
bufsize = match[3].rm_eo-match[3].rm_so + 1;
arr[x].property = (char *) malloc(bufsize);
strncpy(arr[x].property, &(haystack[match[3].rm_so]), bufsize - 1);
arr[x].property[bufsize-1]=0x0;
Get the value from match[4].
bufsize = match[4].rm_eo-match[4].rm_so + 1;
arr[x].value = (char *) malloc(bufsize);\
strncpy(arr[x].value, &(haystack[match[4].rm_so]), bufsize - 1);
arr[x].value[bufsize-1]=0x0;
} else {
Otherwise, set both property and value to NULL.
arr[x].property = NULL;
arr[x].value = NULL;
}
Move the haystack to past the match and decrement the known length.
haystack = &(haystack[match[0].rm_eo]);
l -= match[0].rm_eo;
}
Return the number of matches.
return x+1;
}
Hope this helps. Though it occurs to me now that you never answered kind of a vital question: What have you tried?

Validate mathematical expressions using regular expression?

I want to validate mathematical expressions using regular expression. The mathematical expression can be this
It can be blank means nothing is entered
If specified it will always start with an operator + or - or * or / and will always be followed by a number that can have
any number of digits and the number can be decimal(contains . in between the numbers) or integer(no '.' symbol within the number).
examples : *0.9 , +22.36 , - 90 , / 0.36365
It can be then followed by what is mentioned in point 2 (above line).
examples : *0.9+5 , +22.36*4/56.33 , -90+87.25/22 , /0.36365/4+2.33
Please help me out.
Something like this should work:
^([-+/*]\d+(\.\d+)?)*
Regexr Demo
^ - beginning of the string
[-+/*] - one of these operators
\d+ - one or more numbers
(\.\d+)? - an optional dot followed by one or more numbers
()* - the whole expression repeated zero or more times
You could try generating such a regex using moo and such:
(?:(?:((?:(?:[ \t]+))))|(?:((?:(?:\/\/.*?$))))|(?:((?:(?:(?<![\d.])[0-9]+(?![\d.])))))|(?:((?:(?:[0-9]+\.(?:[0-9]+\b)?|\.[0-9]+))))|(?:((?:(?:(?:\+)))))|(?:((?:(?:(?:\-)))))|(?:((?:(?:(?:\*)))))|(?:((?:(?:(?:\/)))))|(?:((?:(?:(?:%)))))|(?:((?:(?:(?:\()))))|(?:((?:(?:(?:\)))))))
This regex matches any amount of int, float, braces, whitespace, and the operators +-*/%.
However, expressions such as 2+ would still be validated by the regex, so you might want to use a parser instead.
If you want negative or positive expression you can write it like this>
^\-?[0-9](([-+/*][0-9]+)?([.,][0-9]+)?)*?$
And a second one
^[(]?[-]?([0-9]+)[)]??([(]?([-+/*]([0-9]))?([.,][0-9]+)?[)]?)*$
With parenthesis in expression but doesn't count the number you will need method that validate it or regex.
// the method
public static bool IsPairParenthesis(string matrixExpression)
{
int numberOfParenthesis = 0;
foreach (char character in matrixExpression)
{
if (character == '(')
{
numberOfParenthesis++;
}
if (character == ')')
{
numberOfParenthesis--;
}
}
if (numberOfParenthesis == 0)
{ return true; }
return false;
}
This is java regex, but this is only if not have any braces
[+\-]?(([0-9]+\.[0-9]+)|([0-9]+\.?)|(\.?[0-9]+))([+\-/*](([0-9]+\.[0-9]+)|([0-9]+\.?)|(\.?[0-9]+)))*
Also this with braces in java code
In this case I raplace (..) to number (..), should matches without brace pattern
// without brace pattern
static Pattern numberPattern = Pattern.compile("[+\\-]?(([0-9]+\\.[0-9]+)|([0-9]+\\.?)|(\\.?[0-9]+))([+\\-/*](([0-9]+\\.[0-9]+)|([0-9]+\\.?)|(\\.?[0-9]+)))*");
static Pattern bracePattern = Pattern.compile("\\([^()]+\\)");
public static boolean matchesForMath(String txt) {
if (txt == null || txt.isEmpty()) return false;
txt = txt.replaceAll("\\s+", "");
if (!txt.contains("(") && !txt.contains(")")) return numberPattern.matcher(txt).matches();
if (txt.contains("(") ^ txt.contains(")")) return false;
if (txt.contains("()")) return false;
Queue<String> toBeRematch = new ArrayDeque<>();
toBeRematch.add(txt);
while (toBeRematch.size() > 0) {
String line = toBeRematch.poll();
Matcher m = bracePattern.matcher(line);
if (m.find()) {
String newline = line.substring(0, m.start()) + "1" + line.substring(m.end());
String withoutBraces = line.substring(m.start() + 1, m.end() - 1);
toBeRematch.add(newline);
if (!numberPattern.matcher(withoutBraces).matches()) return false;
}
}
return true;
}