I am trying to make a calculator. I am using Regex.Split() to get the number input from the expression. It works well with non-decimal digits but now I am finding a way to get the decimal number input as well.
string mExp = "1.50 + 2.50";
string[] strNum = (Regex.Split(mExp, #"[\D+]"));
num1 = double.Parse(strNum[0]);
num2 = double.Parse(strNum[1]);
You can change your regex to split on some number of spaces followed by an arithmetic operator, followed by spaces:
string[] strNum = (Regex.Split(mExp, #"\s*[+/*-]\s*"));
Console.WriteLine(string.Join("\n", strNum));
Output:
1.50
2.50
Demo on rextester
To deal with negative numbers, you have to make the regex a bit more sophisticated and add a lookbehind for a digit and a lookahead for either a digit or a -:
string mExp = "-1.50 + 2.50 -3.0 + -1";
string[] strNum = (Regex.Split(mExp, #"(?<=\d)\s*[+*/-]\s*(?=-|\d)"));
Console.WriteLine(string.Join("\n", strNum));
Output:
-1.50
2.50
3.0
-1
Demo on rextester
You can use the following regex for splitting for both non-decimal and decimal numbers:
[^\d.]+
Regex Demo
string[] strNum = (Regex.Split(mExp, #"[^\d.]+"));
Essentially saying to match anything except a digit or a dot character recursively and split by that match.
Related
I have a regex code written in C# that basically adds a space between a number and a unit with some exceptions:
dosage_value = Regex.Replace(dosage_value, #"(\d)\s+", #"$1");
dosage_value = Regex.Replace(dosage_value, #"(\d)%\s+", #"$1%");
dosage_value = Regex.Replace(dosage_value, #"(\d+(\.\d+)?)", #"$1 ");
dosage_value = Regex.Replace(dosage_value, #"(\d)\s+%", #"$1% ");
dosage_value = Regex.Replace(dosage_value, #"(\d)\s+:", #"$1:");
dosage_value = Regex.Replace(dosage_value, #"(\d)\s+e", #"$1e");
dosage_value = Regex.Replace(dosage_value, #"(\d)\s+E", #"$1E");
Example:
10ANYUNIT
10:something
10 : something
10 %
40 e-5
40 E-05
should become
10 ANYUNIT
10:something
10: something
10%
40e-5
40E-05
Exceptions are: %, E, e and :.
I have tried, but since my regex knowledge is not top-notch, would someone be able to help me reduce this code with same expected results?
Thank you!
For your example data, you might use 2 capture groups where the second group is in an optional part.
In the callback of replace, check if capture group 2 exists. If it does, use is in the replacement, else add a space.
(\d+(?:\.\d+)?)(?:\s*([%:eE]))?
( Capture group 1
\d+(?:\.\d+)? match 1+ digits with an optional decimal part
) Close group 1
(?: Non capture group to match a as a whole
\s*([%:eE]) Match optional whitespace chars, and capture 1 of % : e E in group 2
)? Close non capture group and make it optional
.NET regex demo
string[] strings = new string[]
{
"10ANYUNIT",
"10:something",
"10 : something",
"10 %",
"40 e-5",
"40 E-05",
};
string pattern = #"(\d+(?:\.\d+)?)(?:\s*([%:eE]))?";
var result = strings.Select(s =>
Regex.Replace(
s, pattern, m =>
m.Groups[1].Value + (m.Groups[2].Success ? m.Groups[2].Value : " ")
)
);
Array.ForEach(result.ToArray(), Console.WriteLine);
Output
10 ANYUNIT
10:something
10: something
10%
40e-5
40E-05
As in .NET \d can also match digits from other languages, \s can also match a newline and the start of the pattern might be a partial match, a bit more precise match can be:
\b([0-9]+(?:\.[0-9]+)?)(?:[\p{Zs}\t]*([%:eE]))?
I think you need something like this:
dosage_value = Regex.Replace(dosage_value, #"(\d+(\.\d*)?)\s*((E|e|%|:)+)\s*", #"$1$3 ");
Group 1 - (\d+(\.\d*)?)
Any number like 123 1241.23
Group 2 - ((E|e|%|:)+)
Any of special symbols like E e % :
Group 1 and Group 2 could be separated with any number of whitespaces.
If it's not working as you asking, please provide some samples to test.
For me it's too complex to be handled just by one regex. I suggest splitting into separate checks. See below code example - I used four different regexes, first is described in detail, the rest can be deduced based on first explanation.
using System.Text.RegularExpressions;
var testStrings = new string[]
{
"10mg",
"10:something",
"10 : something",
"10 %",
"40 e-5",
"40 E-05",
};
foreach (var testString in testStrings)
{
Console.WriteLine($"Input: '{testString}', parsed: '{RegexReplace(testString)}'");
}
string RegexReplace(string input)
{
// First look for exponential notation.
// Pattern is: match zero or more whitespaces \s*
// Then match one or more digits and store it in first capturing group (\d+)
// Then match one ore more whitespaces again.
// Then match part with exponent ([eE][-+]?\d+) and store it in second capturing group.
// It will match lower or uppercase 'e' with optional (due to ? operator) dash/plus sign and one ore more digits.
// Then match zero or more white spaces.
var expForMatch = Regex.Match(input, #"\s*(\d+)\s+([eE][-+]?\d+)\s*");
if(expForMatch.Success)
{
return $"{expForMatch.Groups[1].Value}{expForMatch.Groups[2].Value}";
}
var matchWithColon = Regex.Match(input, #"\s*(\d+)\s*:\s*(\w+)");
if (matchWithColon.Success)
{
return $"{matchWithColon.Groups[1].Value}:{matchWithColon.Groups[2].Value}";
}
var matchWithPercent = Regex.Match(input, #"\s*(\d+)\s*%");
if (matchWithPercent.Success)
{
return $"{matchWithPercent.Groups[1].Value}%";
}
var matchWithUnit = Regex.Match(input, #"\s*(\d+)\s*(\w+)");
if (matchWithUnit.Success)
{
return $"{matchWithUnit.Groups[1].Value} {matchWithUnit.Groups[2].Value}";
}
return input;
}
Output is:
Input: '10mg', parsed: '10 mg'
Input: '10:something', parsed: '10:something'
Input: '10 : something', parsed: '10:something'
Input: '10 %', parsed: '10%'
Input: '40 e-5', parsed: '40e-5'
Input: '40 E-05', parsed: '40E-05'
I want to replace all the floating numbers from a mathematical expression with letters using regular expressions. This is what I've tried:
Regex rx = new Regex("[-]?([0-9]*[.])?[0-9]+");
string expression = "((-30+5.2)*(2+7))-((-3.1*2.5)-9.12)";
char letter = 'a';
while (rx.IsMatch(expression))
{
expression = rx.Replace(expression , letter.ToString(), 1);
letter++;
}
The problem is that if I have for example (5-2)+3 it will replace it to: (ab)+c
So it gets the -2 as a number but I don't want that.
I am not experienced with Regex but I think I need something like this:
Check for '-', if there is a one, check if there is a number or right parenthesis before it. If there is NOT then save the '-'.
After that check for digits + dot + digits
My above Regex also works with values like: .2 .3 .4 but I don't need that, it should be explicit: 0.2 0.3 0.4
Following the suggested logic, you may consider
(?:(?<![)0-9])-)?[0-9]+(?:\.[0-9]+)?
See the regex demo.
Regex details
(?:(?<![)0-9])-)? - an optional non-capturing group matching 1 or 0 occurrences of
(?<![)0-9]) - a place in string that is not immediately preceded with a ) or digit
- - a minus
[0-9]+ - 1+ digits
(?:\.[0-9]+)? - an optional non-capturing group matching 1 or 0 occurrences of a . followed with 1+ digits.
In code, it is better to use a match evaluator (see the C# demo online):
Regex rx = new Regex(#"(?:(?<![)0-9])-)?[0-9]+(?:\.[0-9]+)?");
string expression = "((-30+5.2)*(2+7))-((-3.1*2.5)-9.12)";
char letter = (char)96; // char before a in ASCII table
string result = rx.Replace(expression, m =>
{
letter++; // char is incremented
return letter.ToString();
}
);
Console.WriteLine(result); // => ((a+b)*(c+d))-((e*f)-g)
I want to check the input from the user to make sure that they only enter dots and dashes and any other letters or numbers will give back and error message. Also i wanted to allow the user to enter a space yet when i am converting how can i remove or ignore the white space?
string permutations;
string entered = "";
do
{
Console.WriteLine("Enter Morse Code: \n");
permutations = Console.ReadLine();
.
.
} while(entered.Length != 0);
Thanks!
string permutations = string.Empty;
Console.WriteLine("Enter Morse Code: \n");
permutations = Console.ReadLine(); // read the console
bool isValid = Regex.IsMatch(permutations, #"^[-. ]+$"); // true if it only contains whitespaces, dots or dashes
if (isValid) //if input is proper
{
permutations = permutations.Replace(" ",""); //remove whitespace from string
}
else //input is not proper
{
Console.WriteLine("Error: Only dot, dashes and spaces are allowed. \n"); //display error
}
Let's assume that you separate letters by a single space and words by two spaces. Then you can test if your string is well formatted by using a regular expression like this
bool ok = Regex.IsMatch(entered, #"^(\.|-)+(\ {1,2}(\.|-)+)*$");
Regular expression explained:
^ is the beginning of the string.
\.|- is a dot (escaped with \ as the dot has a special meaning within Regex) or (|) a minus sign.
+ means one or more repetitions of what's left to it (dot or minus).
\ {1,2} one or two spaces (they are followed by dots or minuses again (\.|-)+).
* repeats the space(s) followed by dots or minuses zero or more times.
$ is the end of the line.
You can split the string at the spaces with
string[] parts = input.Split();
Two spaces will create an empty entry. This allows you to detect word boundaries. E.g.
"–– ––– .–. ... . –.–. ––– –.. .".Split();
produces the following string array
{string[10]}
[0]: "––"
[1]: "–––"
[2]: ".–."
[3]: "..."
[4]: "."
[5]: ""
[6]: "–.–."
[7]: "–––"
[8]: "–.."
[9]: "."
I have some text with credit card number inside, like:
"Your credit card number is 4321432143219999, this is really your credit card!"
I need to find by RegEx this number and replace it with ************9999, so result text should be:
"Your credit card number is ************9999, this is really your credit card!"
How can I do it in C#?
Thanks!
var str = "Your credit card number is 4321432143219999, this is really your credit card!";
var res = Regex.Replace(str, "[0-9](?=[0-9]{4})", "*");
This will search for digits that are followed by at least 4 digits and replace it with * (so it would be fooled by 123456 and it would change it in **3456)
If your credit card numbers are 16 digits long:
var res2 = Regex.Replace(str, #"\b[0-9]{12}(?=[0-9]{4}\b)", new string('*', 12));
This will replace a block of 12 digits followed by 4 digits (so a total of 16 digits) with 12x *. The digits must be separated from other text with space or other non-word characters. So A1234567890123456 isn't good, as isn't 1234567890123456A. 1234567890123456, is ok because the , is a non-word character.
It's best to avoid regular expressions whenever possible because they are slower and harder to troubleshoot than ordinary substring operations.
public static string HideNumber(string number)
{
string hiddenString = number.Substring(number.Length - 4).PadLeft(number.Length, '*');
return hiddenString;
}
Is there a simple way to move percentage pointer after the value:
120 # %60 {a} >> 120 # 60% {a}
Try this:
string input = "120 # %60 {a}";
string pattern = #"%(\d+)";
string result = Regex.Replace(input, pattern, "$1%");
Console.WriteLine(result);
The %(\d+) pattern matches a % symbol followed by at least one digit. The digits are captured in a group which is referenced via the $1 in the replacement pattern $1%, which ends up placing the % symbol after the captured number.
If you need to account for numbers with decimal places, such as %60.50, you can use this pattern instead: #"%(\d+(?:\.\d+)?)"