Regex, c# - How to escape all special characters(like $,^,(,),+,[,|,\,.,?,/) at once? [duplicate] - c#

Is there a way to escape the special characters in regex, such as []()* and others, from a string?
Basically, I'm asking the user to input a string, and I want to be able to search in the database using regex. Some of the issues I ran into are too many)'s or [x-y] range in reverse order, etc.
So what I want to do is write a function to do replace on the user input. For example, replacing ( with \(, replacing [ with \[
Is there a built-in function for regex to do so? And if I have to write a function from scratch, is there a way to account all characters easily instead of writing the replace statement one by one?
I'm writing my program in C# using Visual Studio 2010

You can use .NET's built in Regex.Escape for this. Copied from Microsoft's example:
string pattern = Regex.Escape("[") + "(.*?)]";
string input = "The animal [what kind?] was visible [by whom?] from the window.";
MatchCollection matches = Regex.Matches(input, pattern);
int commentNumber = 0;
Console.WriteLine("{0} produces the following matches:", pattern);
foreach (Match match in matches)
Console.WriteLine(" {0}: {1}", ++commentNumber, match.Value);
// This example displays the following output:
// \[(.*?)] produces the following matches:
// 1: [what kind?]
// 2: [by whom?]

you can use Regex.Escape for the user's input

string matches = "[]()*";
StringBuilder sMatches = new StringBuilder();
StringBuilder regexPattern = new StringBuilder();
for(int i=0; i<matches.Length; i++)
sMatches.Append(Regex.Escape(matches[i].ToString()));
regexPattern.AppendFormat("[{0}]+", sMatches.ToString());
Regex regex = new Regex(regexPattern.ToString());
foreach(var m in regex.Matches("ADBSDFS[]()*asdfad"))
Console.WriteLine("Found: " + m.Value);

Related

I need to get a word before another one that always stay the same in string

In this text, swerve means:
I want the word before "means". In the above text, I want the word "swerve". The word "means" is always at the same place, but the word before it changes.
How can I get the before "means"?
You can achieve this via Regex expressions like others mentioned in here, but I'd recommend a nuget package to add called "Sprache". Take a look at it here.
You can use regex
string input = "In this text, swerve means:"; //your input string..
var word = Regex.Match(input, "In this text, (.+?) means:").Groups[1].Value;
or simple string ops like
var word = input.Split()[3];
You could use a regex:
(\w+)(?=\W+means)
Or with full code:
string input = "In this text, swerve means";
Regex regex = new Regex(#"(\w+)(?=\W+means)");
foreach (Match m in regex.Matches(input)) {
Console.WriteLine(m.Groups[1].Value);
}
This will iterate through all matches it can find and print these words. It will furthermore print "means" twice in case you write "means means means".
In the C# interactive shell, this generates:
csharp> string input = "In this text, swerve means";
csharp> Regex regex = new Regex(#"(\w+)(?=\W+means)");
csharp> foreach (Match m in regex.Matches(input)) {
> Console.WriteLine(m.Groups[1].(alue); error CS0103: The name `m' does not exist in the current context
> }
swerve

Escape Special Character in Regex

Is there a way to escape the special characters in regex, such as []()* and others, from a string?
Basically, I'm asking the user to input a string, and I want to be able to search in the database using regex. Some of the issues I ran into are too many)'s or [x-y] range in reverse order, etc.
So what I want to do is write a function to do replace on the user input. For example, replacing ( with \(, replacing [ with \[
Is there a built-in function for regex to do so? And if I have to write a function from scratch, is there a way to account all characters easily instead of writing the replace statement one by one?
I'm writing my program in C# using Visual Studio 2010
You can use .NET's built in Regex.Escape for this. Copied from Microsoft's example:
string pattern = Regex.Escape("[") + "(.*?)]";
string input = "The animal [what kind?] was visible [by whom?] from the window.";
MatchCollection matches = Regex.Matches(input, pattern);
int commentNumber = 0;
Console.WriteLine("{0} produces the following matches:", pattern);
foreach (Match match in matches)
Console.WriteLine(" {0}: {1}", ++commentNumber, match.Value);
// This example displays the following output:
// \[(.*?)] produces the following matches:
// 1: [what kind?]
// 2: [by whom?]
you can use Regex.Escape for the user's input
string matches = "[]()*";
StringBuilder sMatches = new StringBuilder();
StringBuilder regexPattern = new StringBuilder();
for(int i=0; i<matches.Length; i++)
sMatches.Append(Regex.Escape(matches[i].ToString()));
regexPattern.AppendFormat("[{0}]+", sMatches.ToString());
Regex regex = new Regex(regexPattern.ToString());
foreach(var m in regex.Matches("ADBSDFS[]()*asdfad"))
Console.WriteLine("Found: " + m.Value);

Regex to extract Variable Part

I have a string containing this: #[User::RootPath]+"Dim_MyPackage10.dtsx" and I need to extract the [User::RootPath] part using a regex. So far I have this regex: [a-zA-Z0-9]*\.dtsx but I don't know how to proceed further.
For the variable, why not consume what is needed by using the not set [^ ] to extract everything except in the set?
The ^ in the braces means find what is not matched, such as this where it seeks all that is not a ] or a quote (").
Then we can place the actual matches in named capture groups (?<{NameHere}> ) and extract accordingly
string pattern = #"(?:#\[)(?<Path>[^\]]+)(?:\]\+\"")(?<File>[^\""]+)(?:"")";
// Pattern is (?:#\[)(?<Path>[^\]]+)(?:\]\+\")(?<File>[^\"]+)(?:")
// w/o the "'s escapes for the C# parser
string text = #"#[User::RootPath]+""Dim_MyPackage10.dtsx""";
var result = Regex.Match(text, pattern);
Console.WriteLine ("Path: {0}{1}File: {2}",
result.Groups["Path"].Value,
Environment.NewLine,
result.Groups["File"].Value
);
/* Outputs
Path: User::RootPath
File: Dim_MyPackage10.dtsx
*/
(?: ) is match but don't capture, because we use those as defacto anchors for our pattern and to not place them into the match capture groups.
Use this regex pattern:
\[[^[\]]*\]
Check this demo.
Your regex will match any number of alphanumeric characters, followed by .dtsx. In your example, it would match MyPackage10.dtsx.
If you want to match Dim_MyPackage10.dtsx you need to add an underscore to your list of allowed characters in the regex: [a-zA-Z0-9]*.dtsx
If you want to match the [User::RootPath], you need a regex that will stop at the last / (or \, depends on which type of slashes you use in the paths): something like this: .*\/ (or .*\\)
From the answers and comments - and the fact that none has been 'accepted' so far - it appears to me that the question/problem is not completely clear. If you're looking for the pattern [User::SomeVariable] where only 'SomeVariable' is, well, variable, then you may try:
\[User::\w+]
to capture the full expression.
Furthermore, if you wish to detect that pattern, but then need only the "SomeVariable" part, you may try:
(?<=\[User::)\w+(?=])
which uses look-arounds.
Here it is bro
using System;
using System.Text.RegularExpressions;
namespace myapp
{
class Class1
{
static void Main(string[] args)
{
String sourcestring = "source string to match with pattern";
Regex re = new Regex(#"\[\S+\]");
MatchCollection mc = re.Matches(sourcestring);
int mIdx=0;
foreach (Match m in mc)
{
for (int gIdx = 0; gIdx < m.Groups.Count; gIdx++)
{
Console.WriteLine("[{0}][{1}] = {2}", mIdx, re.GetGroupNames()[gIdx], m.Groups[gIdx].Value);
}
mIdx++;
}
}
}
}

c# Regex question

I have a problem dealing with the # symbol in Regex, I am trying to remove #sometext
from a text string can't seem to find anywhere where it uses the # as a literal. I have tried myself but doesn't remove the word from the string. Any ideas?
public string removeAtSymbol(string input)
{
Regex findWords = new Regex(______);//Find the words like "#text"
Regex[] removeWords;
string test = input;
MatchCollection all = findWords.Matches(test);
removeWords = new Regex[all.Count];
int index = 0;
string[] values = new string[all.Count];
YesOutputBox.Text = " you got here";
foreach (Match m in all) //List all the words
{
values[index] = m.Value.Trim();
index++;
YesOutputBox.Text = YesOutputBox.Text + " " + m.Value;
}
for (int i = 0; i < removeWords.Length; i++)
{
removeWords[i] = new Regex(" " + values[i]);
// If the words appears more than one time
if (removeWords[i].Matches(test).Count > 1)
{
removeWords[i] = new Regex(" " + values[i] + " ");
test = removeWords[i].Replace(test, " "); //Remove the first word.
}
}
return test;
}
You can remove all occurences of "#sometext" from string test via the method
Regex.Replace(test, "#sometext", "")
or for any word starting with "#" you can use
Regex.Replace(test, "#\\w+", "")
If you need specifically a separate word (i.e. nothing like #comp within tom#comp.com) you may preceed the regex with a special word boundary (\b does not work here):
Regex.Replace(test, "(^|\\W)#\\w+", "")
You can use:
^\s#([A-Za-z0-9_]+)
as the regex to recognize Twitter usernames.
Regex to remove #something from this string: I want to remove #something from this string.
var regex = new Regex("#\\w*");
string result = regex.Replace(stringWithAt, "");
Is that what you are looking for?
I've had good luck applying this pattern:
\B#\w+
This will match any string starting with an # character that contains alphanumeric characters, plus some linking punctuation like the underscore character, if it does not occur on a boundary between alphanumeric and non-alphanumeric characters.
The result of executing this code:
string result = Regex.Replace(
#"#This1 #That2_thing this2#3that #the5Others #alpha#beta#gamma",
#"\B#\w+",
#"redacted");
is the following string:
redacted redacted this2#3that redacted redacted#beta#gamma
If this question is Twitter-specific, then Twitter provides an open source library that helps capture Twitter-specific entities like links, mentions and hashtags. This java file contains the code defining the regular expressions that Twitter uses, and this yml file contains test strings and expected outcomes of many unit tests that exercise the regular expressions in the Twitter library.
Twitter's mention-matching pattern (extracted from their library, modified to remove unnecessary capture groups, and edited to make sense in the context of a replacement) is shown below. The match should be performed in a case-insensitive manner.
(^|[^a-z0-9_])[#\uFF20][a-z0-9_]{1,20}
Here is an example which reproduces the results of the first replacement in my answer:
string result = Regex.Replace(
#"#This1 #That2_thing this2#3that #the5Others #alpha#beta#gamma",
#"(^|[^a-z0-9_])[#\uFF20][a-z0-9_]{1,20}",
#"$1redacted",
RegexOptions.IgnoreCase);
Note the need to include the substitution $1 since the first capture group can't be directly converted into an atomic zero-width assertion.

Regex matching key="value" pattern

I want to match following pattern:
key="value" key="value" key="value" key="value" ...
where key and value are [a-z0-9]+, both should be grouped (2 groups, the " - chars can be matched or skipped)
input that should not be matched:
key="value"key="value" (no space between pairs)
For now I got this(not .NET syntax):
([a-z0-9]+)=(\"[a-z0-9]+\")(?=\s|$)
the problem with that, that it matches key4="value4" in input:
key3="value3"key4="value4"
The spec isn't very clear, but you can try:
(?<!\S)([a-z0-9]+)=("[a-z0-9]+")(?!\S)
Or, as a C# string literal:
"(?<!\\S)([a-z0-9]+)=(\"[a-z0-9]+\")(?!\\S)"
This uses a negative lookarounds to ensure that the the key-value pair is neither preceded nor followed by non-whitespace characters.
Here's an example snippet (as seen on ideone.com):
var input = "key1=\"value1\" key2=\"value2\"key3=\"value3\" key4=\"value4\"";
Console.WriteLine(input);
// key1="value1" key2="value2"key3="value3" key4="value4"
Regex r = new Regex("(?<!\\S)([a-z0-9]+)=(\"[a-z0-9]+\")(?!\\S)");
foreach (Match m in r.Matches(input)) {
Console.WriteLine(m);
}
// key1="value1"
// key4="value4"
Related questions
How does the regular expression (?<=#)[^#]+(?=#) work?
On validating the entire input
You can use Regex.IsMatch to see if the input string matches against what should be the correct input pattern. You can also use the same pattern to extract the keys/values, thanks to the fact that .NET regex lets you access individual captures.
string[] inputs = {
"k1=\"v1\" k2=\"v2\" k3=\"v3\" k4=\"v4\"",
"k1=\"v1\" k2=\"v2\"k3=\"v3\" k4=\"v4\"",
" k1=\"v1\" k2=\"v2\" k3=\"v3\" k4=\"v4\" ",
" ",
" what is this? "
};
Regex r = new Regex("^\\s*(?:([a-z0-9]+)=\"([a-z0-9]+)\"(?:\\s+|$))+$");
foreach (string input in inputs) {
Console.Write(input);
if (r.IsMatch(input)) {
Console.WriteLine(": MATCH!");
Match m = r.Match(input);
CaptureCollection keys = m.Groups[1].Captures;
CaptureCollection values = m.Groups[2].Captures;
int N = keys.Count;
for (int i = 0; i < N; i++) {
Console.WriteLine(i + "[" + keys[i] + "]=>[" + values[i] + "]");
}
} else {
Console.WriteLine(": NO MATCH!");
}
}
The above prints (as seen on ideone.com):
k1="v1" k2="v2" k3="v3" k4="v4": MATCH!
0[k1]=>[v1]
1[k2]=>[v2]
2[k3]=>[v3]
3[k4]=>[v4]
k1="v1" k2="v2"k3="v3" k4="v4": NO MATCH!
k1="v1" k2="v2" k3="v3" k4="v4" : MATCH!
0[k1]=>[v1]
1[k2]=>[v2]
2[k3]=>[v3]
3[k4]=>[v4]
: NO MATCH!
what is this? : NO MATCH!
References
Is there a regex flavor that allows me to count the number of repetitions matched by the * and + operators?
Explanation of the pattern
The pattern to validate the entire input is essentially:
maybe leading
spaces ___ end of string anchor
| /
^\s*(entry)+$
| \
beginning \__ one or more entry
of string
anchor
Where each entry is:
key=value(\s+|$)
That is, a key/value pair followed by either spaces or the end of the string.
I think SilentGhost proposal is about using String.Split()
Like this :
String keyValues = "...";
foreach(String keyValuePair in keyValues.Split(' '))
Console.WriteLine(keyValuePair);
This is definitively faster and simpler.
Use a lookbehind like you used your lookahead:
(?<=\s|^)([a-z0-9]+)=(\"[a-z0-9]+\")(?=\s|$)
I second Jens' answer (but am still too puny to comment on others' answers).
Also, I've found this Regular Expressions Reference site to be quite awesome. There's a section on Lookaround about halfway down on the Advanced page, and some further notes about Lookbehind.

Categories

Resources