I am using VB.NET to write a winforms application, how can I use regular expression to remove spaces between "[" and "]" in a string?
For example, for a string
"[Product Name] Like '%Dragon Ball%' AND [Product Type] Like '%Toy%'"
I want the result to be
"[ProductName] Like '%Dragon Ball%' AND [ProductType] Like '%Toy%'"
I tried this, but it is not working:
Public Function RemoveSpaceInFieldNames(ByVal expression As String) As String
Dim regex As RegularExpressions.Regex = New
RegularExpressions.Regex(String.Format("\{0}\s*\{1}", "[", "]"))
Return regex.Replace(expression, String.Empty)
End Function
See regex in use here
(?<=\[[^]]*)\s
(?<=\[[^]]*) Positive lookbehind ensuring the following matches
\[ Match [ literally
[^]]* Match any character except ] any number of times
\s Match any whitespace character
You can append (?=[^[]*]) if you want to ensure there's a ] sometime afterwards as well, but, based on your sample, I don't think this is necessary.
Alternatively, you can also use \s(?=[^[]*]) with the Right to Left modifier as this link shows.
Replace with an empty string.
Result: [ProductName] Like '%Dragon Ball%' AND [ProductType] Like '%Toy%'
Thank you so much ctwheels! Your answer works perfectly!!!
Public Function RemoveSpaceInFieldNames(ByVal expression As String) As String
Dim regex As RegularExpressions.Regex = New RegularExpressions.Regex("(?<=\[[^]]*)\s")
Return regex.Replace(expression, String.Empty)
End Function
Related
How to split string with Regex.Split and keep all separators?
I have a string:"substring1 delimeter1 substring2" , where delimeter+substring2 is a part of address.
Also i have 2 and more delimeters: delim1,delim2 wich are equivalent in meaning;
And i want to get string array like this:
arr[0]="subsctring1";
arr[1]="delim1 subsctring2";
or,
arr[1]="delim2 subsctring2;
I have a pattern:
addrArr= Regex.Split(inputText, String.Concat("(?<=",delimeter1, "|",delimeter2, ")"), RegexOptions.None);
But it not works well.
Can you help me to create a valid pattern to to that?
You need a pattern with a lookahead only:
\s+(?=delim1|delim2)
The \s+ will match 1 or more whitespaces (since your string contains whitespaces). In case there can be no whitespaces, use \s* (but then you will need to remove empty entries from the result). See the regex demo. If these delimiters must be whole words, use \b word boundaries: \s+(?=\b(?:delim1|delim2)\b).
In C#:
addrArr = Regex.Split(inputText, string.Format(#"\s+(?={0})", string.Join("|", delimeters)));
If the delimiters can contain special regex metacharacters, you will need to run Regex.Escape on your delimiters list.
A C# demo:
var inputText = "substring1 delim1 substring2 delim2 substr3";
var delimeters = new List<string> { "delim1", "delim2" };
var addrArr = Regex.Split(inputText,
string.Format(#"\s+(?={0})", string.Join("|", delimeters.Select(Regex.Escape))));
Console.WriteLine(string.Join("\n", addrArr));
I think you need to use a lookahead, not a lookbehind, for this to work (haven't tried it though).
Also, you have to be careful with the separators; they must be escaped to work correctly as patterns in the regex.
Try this:
addrArr= Regex.Split(inputText, string.Format("(?={0}|{1})", Regex.Escape(delimeter1), Regex.Escape(delimeter2)), RegexOptions.None);
Given string:
some_function(inputId = "select_something"),
(...)
some_other_function(inputId = "some_other_label")
I would like to arrive at:
some_function(inputId = ns("select_something")),
(...)
some_other_function(inputId = ns("some_other_label"))
The key change here is the element ns( ... ) that surrounds the string available in the "" after the inputId
Regex
So far, I have came up with this regex:
:%substitute/\(inputId\s=\s\)\(\"[a-zA-Z]"\)/\1ns(/2/cgI
However, when deployed, it produces an error:
E488: Trailing characters
A simpler version of that regex works, the syntax:
:%substitute/\(inputId\s=\s\)/\1ns(/cgI
would correctly inser ns( after finding inputId = and create string
some_other_function(inputId = ns("some_other_label")
Challenge
I'm struggling to match the remaining part of the string, ex. "select_something") and return it as:
"select_something")).
You have many problems with your regex.
[a-zA-Z] will only match one letter. Presumably you want to match everything up to the next ", so you'll need a \+ and you'll also need to match underscores too. I would recommend \w\+. Unless more than [a-zA-Z_] might be in the string, in which case I would do .\{-}.
You have a /2 instead of \2. This is why you're getting E488.
I would do this:
:%s/\(inputId = \)\(".\{-}\)"/\1ns(\2)/cgI
Or use the start match atom: (that is, \zs)
:%s/inputId = \zs\".\{-}"/ns(&)/cgI
You can use a negated character class "[^"]*" to match a quoted string:
%s/\(inputId\s*=\s*\)\("[^"]*"\)/\1ns(\2)/g
I'd like to capture the value of the Initial Catalog in this string:
"blah blah Initial Catalog = MyCat'"
I'd like the result to be: MyCat
There could or could not be spaces before and after the equal sign and there could or could not be spaces before the single quote.
Tried this and various others but no go:
/Initial Catalog\s?=\s?.*\s?\'/
Using .Net.
You need to put parentheses around the part of the string that you would like to match:
/Initial Catalog\s*=\s*(.*?)\s*'/
Also you would like to exclude as many spaces as possible before the ', so you need \s* rather than \s?. The .*? means that the extracted part of the string doesn't take those spaces, since it is now lazy.
This is a nice regex
= *(.*?) *'
Use the idea and add \s and more literal text as needed.
In C# group 1 will contain the match
string resultString = null;
try {
Regex regexObj = new Regex("= *(.*?) *'");
resultString = regexObj.Match(subjectString).Groups[1].Value;
} catch (ArgumentException ex) {
// Syntax error in the regular expression
}
Regex rgx = new Regex(#"=\s*([A-z]+)\s*'");
String result = rgx.Match(text).Groups[1].Value;
I'm working on String Calculator code kata with Groovy.
There are a lot of scenarios that solve for achieve the solution:
I have:
//;\n1;2;3
//#\n1#2#3
//+\n1+2+3
//*\n1*2*3
//?\n1?2?3
I want:
1,2,3
My implementation:
String numbers = "//;\n1;2;3"
numbers.find(/\/\/\S[\n]/) { match ->
def delimeter = match[2]
numbers = numbers.minus(match).replaceAll(delimeter, ",")
}
With this solution I solved the first and second expressions, but I don't know how solve the others expressions.
java.util.regex.PatternSyntaxException: Dangling meta character '+' near index 0
The problem is that we must also consider any symbol that match with the sintaxt of regular expressions like +, * or ?
Finally I have the solution:
String numbers = "//+\n1+2+3"
numbers.find(/(?s)\/\/(.*)\n/) { match ->
def delimeter = match[1] // also match[0][2]
numbers = numbers.minus(match[0]).replace(delimeter, ",")
}
An important point (?s):
In dotall mode, the expression . matches any character, including a line terminator. By default this expression does not match line terminators.
Dotall mode can also be enabled via the embedded flag expression (?s)
But really the problem was here: .replace(delimeter, ",")
//(.)\n(\d)\1(\d)\1(\d)
Need to use links.
(.) - math thiw any character, and \1 - math thiw character on it\
For next example you can apply this: //\[(.*?)\]\\n(\d)\1(\d)\1(\d)
It math thiw
//[*]\n12**3
And last: //\[(.*?)\]\[(.*?)\]\\n(\d)\1(\d)\2(\d)
//[*][%%]\n1*2%%3
And finaly:
//\[(.*?)\](?:\[(.*?)\])?\\n(\d)\1(\d)(?:\2|\1)(\d)
I think it's can work ewerythere
P.S : (\d) you can replace what you want. I think you need (\d*)
Excel returns a reference of the form
=Sheet1!R14C1R22C71junk
("junk" won't normally be there, but I want to be sure that there's no extraneous text.)
I would like to 'split' this into a VB array, where
a(0)="Sheet1"
a(1)="14"
a(2)="1"
a(3)="22"
a(4)="71"
a(5)="junk"
I'm sure it can be done easily with a regular expression, but I just can't get the hang of it.
Is there a kind soul who could help me?
Thanks
=([^!]+)!R(\d+)C(\d+)R(\d+)C(\d+)(.*)
should work.
[^!]+ matches a sequence of non-exclamation-point characters.
\d+ matches a sequence of digits.
.* matches anything.
So, in VB.NET:
Dim a As Match
a = Regex.Match(SubjectString, "=([^!]+)!R(\d+)C(\d+)R(\d+)C(\d+)(.*)")
If a.Success Then
' matched text: a.Value
' backreference n text: a.Groups(n).Value
Else
' Match attempt failed
End If
A straightforward String.Split would work, provided the "junk" text wasn't there:
Dim input As String = "=Sheet1!R14C1R22C71"
Dim result = input.Split(New Char() { "="c, "!"c, "R"c, "C"c }, StringSplitOptions.RemoveEmptyEntries)
For Each item As String In result
Console.WriteLine(item)
Next
The regex gets a little tricky since you will need to go through the Groups and Captures of the nested portions to get the proper order.
EDIT: here's my regex solution. It accepts multiple occurrences of R's and C's.
Dim input As String = "=Sheet1!R14C1R22C71junk"
Dim pattern As String = "=(?<Sheet>Sheet\d+)!(?:R(?<R>\d+)C(?<C>\d+))+"
Dim m As Match = Regex.Match(input, pattern)
If m.Success Then
Console.WriteLine(m.Groups("Sheet").Value)
For i = 0 To m.Groups("R").Captures.Count - 1
Console.WriteLine(m.Groups("R").Captures(i).Value)
Console.WriteLine(m.Groups("C").Captures(i).Value)
Next
End If
Pattern explanation:
"=(?Sheet\d+)" : matches an = sign followed by "Sheet" and digits. Uses named group of "Sheet"
"!(?:R(?\d+)C(?\d+))+" : matches the exclamation mark followed by at least one occurrence of the *R*xx*C*xx portion of the text. Named groups of "R" and "C" are used.
"(?:...)+" : this portion from the above portion matches but does not capture the inner pattern (i.e., the R/C part). This is to avoid unnecessarily capturing them while we are actually capturing them with the named groups.
More general regexes for R1C1 style:
^=(?:(?<Sheet>[^!]+)!)?(?:R((?<RAbs>\d+)|(?<RRel>\[-?\d+\]))C((?<CAbs>\d+)|(?<CRel>\[-?\d+\]))){1,2}$
And A1 style:
^=(?:(?<Sheet>[^!]+)!)?(?:(?<Col1>\$?[a-z]+)(?<Row1>\$?\d+))(?:\:(?<Col2>\$?[a-z]+)(?<Row2>\$?\d+))?$
It doesn't match external references like =[Book1]Sheet1!A1 though.