I am attempting to use regex matching to get a list of optional params out of an mvc route and dynamically inject values into the holders where variables have been used. See code below. Unfortunatly the sample doesn't find both values but repeats the first. Can anyone offer any help?
using System;
using System.Text.RegularExpressions;
namespace regexTest
{
class Program
{
static void Main(string[] args)
{
var inputstr = "http://localhost:12345/Controller/Action/{route:value1}/{route:value2}";
var routeRegex = new Regex(#"(?<RouteVals>{route:[\w]+})");
var routeMatches = routeRegex.Match(inputstr);
for (var i = 0; i < routeMatches.Groups.Count; i++)
{
Console.WriteLine(routeMatches.Groups[i].Value);
}
Console.ReadLine();
}
}
}
This outputs
{route:value1}
{route:value1}
where I was hopeing to get
{route:value1}
{route:value2}
I know nothing about C# but it may help if you put the quantifier after the closing parenthese, no?
Update: That post may help you.
Just make a global match :
var inputstr = "http://localhost:12345/Controller/Action/{route:value1}/{route:value2}";
StringCollection resultList = new StringCollection();
Regex regexObj = new Regex(#"\{route:\w+\}");
Match matchResult = regexObj.Match(inputstr);
while (matchResult.Success) {
resultList.Add(matchResult.Value);
matchResult = matchResult.NextMatch();
}
Your results will be stored in resultList.
foreach (Match match in routeMatches){
for(var i=1;i<match.Groups.Count;++i)
Console.WriteLine(match.Groups[i].Value);
}
Related
Hello i'm new at C# and programming so i get stuck for hours to get the last result from my looping result
here my code :
using System;
public class Program
{
public static void Main()
{
string merek = string.Empty;
// i wanted to get the last value which is 13 R DLX DG M/T
string str = "DAIHATSU.ALL NEW XENIA.13 R DLX DG M/T";
// Taking a string
char[] spearator = { '.', '.' };
// using the method
String[] strlist = str.Split(spearator);
foreach(String s in strlist)
{
Console.WriteLine(s);
}
}
}
this the point
the result is
DAIHATSU
ALL NEW XENIA
13 R DLX DG M/T
// i wanted to get the last value which is 13 R DLX DG M/T
string str = "DAIHATSU.ALL NEW XENIA.13 R DLX DG M/T";
i'm really appreciate for any help thank you.
You don't need a for loop. You can simply print the last part using the following:
Console.WriteLine(strlist[strlist.Length - 1]);
You can use IEnumerable<T>.Last():
var last = strlist.Last();
Remember to include Linq:
using System.Linq;
Based on your title question, you are looking for the last value after looping.
You can access it directly from your string array.
strlist[strlist.Length - 1];
If there is any valid reason to go through the array, another alternative would be this
string latest = "";
foreach(String s in strlist)
{
Console.WriteLine(s);
latest = s;
}
// After the loop, the latest variable will have the value you are looking for.
To avoid using another Linq cal, you could try using the "IsLast" property from the SmartEnumerable Extension from Jon Skeet's old but reliable MiscUtil. Here's a link to a port into modern .net
https://github.com/jaredthirsk/JTForks.MiscUtil/blob/master/JTForks.MiscUtil/Collections/SmartEnumerable.cs
I have a string that looks like this
2,"E2002084700801601390870F"
3,"E2002084700801601390870F"
1,"E2002084700801601390870F"
4,"E2002084700801601390870F"
3,"E2002084700801601390870F"
This is one whole string, you can imagine it being on one row.
And I want to split this in the way they stand right now like this
2,"E2002084700801601390870F"
I cannot change the way it is formatted. So my best bet is to split at every second quotation mark. But I haven't found any good ways to do this. I've tried this https://stackoverflow.com/a/17892392/2914876 But I only get an error about invalid arguements.
Another issue is that this project is running .NET 2.0 so most LINQ functions aren't available.
Thank you.
Try this
var regEx = new Regex(#"\d+\,"".*?""");
var lines = regex.Matches(txt).OfType<Match>().Select(m => m.Value).ToArray();
Use foreach instead of LINQ Select on .Net 2
Regex regEx = new Regex(#"\d+\,"".*?""");
foreach(Match m in regex.Matches(txt))
{
var curLine = m.Value;
}
I see three possibilities, none of them are particularly exciting.
As #dvnrrs suggests, if there's no comma where you have line-breaks, you should be in great shape. Replace ," with something novel. Replace the remaining "s with what you need. Replace the "something novel" with ," to restore them. This is probably the most solid--it solves the problem without much room for bugs.
Iterate through the string looking for the index of the next " from the previous index, and maintain a state machine to decide whether to manipulate it or not.
Split the string on "s and rejoin them in whatever way works the best for your application.
I realize regular expressions will handle this but here's a pure 2.0 way to handle as well. It's much more readable and maintainable in my humble opinion.
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
const string data = #"2,""E2002084700801601390870F""3,""E2002084700801601390870F""1,""E2002084700801601390870F""4,""E2002084700801601390870F""3,""E2002084700801601390870F""";
var parsedData = ParseData(data);
foreach (var parsedDatum in parsedData)
{
Console.WriteLine(parsedDatum);
}
Console.ReadLine();
}
private static IEnumerable<string> ParseData(string data)
{
var results = new List<string>();
var split = data.Split(new [] {'"'}, StringSplitOptions.RemoveEmptyEntries);
if (split.Length % 2 != 0)
{
throw new Exception("Data Formatting Error");
}
for (var index = 0; index < split.Length / 2; index += 2)
{
results.Add(string.Format(#"""{0}""{1}""", split[index], split[index + 1]));
}
return results;
}
}
}
I have a bad word list. If a string contains any of item/items from the bad word list, I need to remove that bad word from the string.
List<string> badWordList = new List<string> { "email:", "index", "mobile:", "fax:", "web" };
I am able to search the string but not able to remove. Please help me out...I tried below code:
string myText = "email:abc#gmail.com";
if (badWordList.Any(w => myText.IndexOf(w, StringComparison.OrdinalIgnoreCase) >= 0))
{
// How to remove
}
Below is the set of input of expected output:
i/p- email:abc#gmail.com
o/p - abc#gmail.com
i/p- Jack F. Mobile:89788987
o/p- Jack F. 89788987
i/p- Jack F. Email:t#p.c mobile:65777 WEB
o/p- Jack F. t#p.c 65777
I would prefer a non-regex approach. Thanks for your help.
You can iterate on the bad words and remove them:
foreach (string badWord in badWordList) {
myText = myText.Replace(badWord, string.Empty);
}
If you need a case-insensitive solution you can use the overload with a StringComparison parameter:
myText = myText.Replace(badWord, string.Empty, StringComparison.OrdinalIgnoreCase);
Note: a previous version of this answer, which is quite old, and some of the comments to this question, suggested to use a Regex for a case-insensitive string replacement (see example below).
I think that now that there is the overload with the StringComparison it's much better to just use that.
string myText = "EMAIL:abc#gmail.com";
Regex badWords = new Regex("email:|index|mobile:|fax:|web", RegexOptions.IgnoreCase | RegexOptions.Compiled);
myText = badWords.Replace(myText, string.Empty);
You can remove strings by replacing them with the empty string:
foreach (var badWord in badWordList)
{
myText = myText.Replace(badWord, "");
}
Unfortulately this is case sensitive. For case-insensitive string replace without regular expressions, see Is there a case insensitive string replace in .Net without using Regex?
You can also do it with a regular expression, in which case case-insensitive comparison comes "for free":
var regex = String.Join("|", badWordList.Select(w => Regex.Escape(w)));
var myText = Regex.replace(myText, regex, "", RegexOptions.IgnoreCase);
Replace the instance of the 'bad word' with string.Empty: -
List<string> badWordList = new List<string> { "email", "index:", "mobile:", "fax:", "web" };
string myText = "email:abc#gmail.com";
foreach (string s in badWordList)
{
myText = myText.Replace(s,string.Empty);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace WindowMaker
{
class Program
{
static void Main(string[] args)
{
System.Console.WriteLine("Enter Main string...");
String str = System.Console.ReadLine();
System.Console.WriteLine("Enter sub string...");
String sub = System.Console.ReadLine();
Boolean flag;
int strlen=sub.Length;
int inde = str.IndexOf(sub);
while (inde != -1)
{
inde = str.IndexOf(sub);
str=str.Replace(sub,"");
}
System.Console.WriteLine("Remaining string :: {0}",str);
Console.Read();
}
}
}
if it is case sensitive :
List<String> badWordList = new List<String> { "email:", "index", "mobile:", "fax:", "web" };
String myText = "This is a exemple of Email: deleting with index and fax and web";
badWordList.ForEach(bw => myText = myText.Replace(bw, String.Empty));
I am looking to write a utility to batch rename a bunch of files at once using a regular expression. The files that I will be renaming all at once follow a certain naming convention, and I want to alter them to a new naming convention using data that's already in the filenames; but not all my files follow the same convention currently.
So I want to be able to write a general use program that lets me input into a textbox during runtime the pattern of the filename, and what tokens I want to extract from the filename to use for renaming.
For example - Assume I have one file named [Coalgirls]_Suite_Precure_02_(1280x720_Blu-Ray_FLAC)_[33D74D55].mkv. I want to be able to rename this file to Suite Precure - Ep 02 [Coalgirls][33D74D55].mkv
This means I would preferably be able to enter into my program before renaming something akin to [%group%]_Suite_Precure_%ep%_(...)_[%crc%].mkv and it would populate the local variables group, ep, and crc to use in the batch rename.
One particular program I'm thinking of that does this is mp3tag, used for converting file names to id3 tags. It lets you put something like %artist% - %album% - %tracknumber% - %title%, and it takes those 4 tokens and puts them into the respective id3 tags.
How can I make a system similar to this without having to make the user know regex syntax?
As mentioned by usr, you can extract all the named placeholders in the search string using %(?<name>[^%]+)%. This will get you "group", "ep", and "crc".
Now you need to scan all the fragments between the placeholders and put a capture at each placeholder in the regex. I'd iterate through the matches from above (you can get start offset and length of each match to navigate through the non-placeholder fragments).
(There are mistakes in your example, I'll assume the last part is correct and I'm dropping the mysterious (...))
It would build a regex that looks like this:
^%(?<group>.*?)_Suite_Precure_(?<ep>.*?)_(?<crc>.*?).mkv$
Pass the literal fragments to Regex.Escape before using it in the regex to handle troublesome characters properly.
Now, for each filename, you try to match the regex to it. If it matches, you get the values of the placeholders for this file. Then you take those placeholder values and merge them into the output pattern, replacing the placeholders appropriately. This gives you the new name, you can do the rename.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace renamer
{
class RenameImpl
{
public static IEnumerable<Tuple<string,string>> RenameWithPatterns(
string path, string curpattern, string newpattern,
bool caseSensitive)
{
var placeholderNames = new List<string>();
// Extract all the cur_placeholders from the user's input pattern
var input_regex = new Regex(#"(\%[^%]+\%)");
var cur_matches = input_regex.Matches(curpattern);
var new_matches = input_regex.Matches(newpattern);
var regex_pattern = new StringBuilder();
if (!caseSensitive)
regex_pattern.Append("(?i)");
regex_pattern.Append('^');
// Do a pass over the matches and grab info about each capture
var cur_placeholders = new List<Tuple<string, int, int>>();
var new_placeholders = new List<Tuple<string, int, int>>();
for (var i = 0; i < cur_matches.Count; ++i)
{
var m = cur_matches[i];
cur_placeholders.Add(new Tuple<string, int, int>(
m.Value, m.Index, m.Length));
}
for (var i = 0; i < new_matches.Count; ++i)
{
var m = new_matches[i];
new_placeholders.Add(new Tuple<string, int, int>(
m.Value, m.Index, m.Length));
}
// Build the regular expression
for (var i = 0; i < cur_placeholders.Count; ++i)
{
var ph = cur_placeholders[i];
// Get the literal before the first capture if it is the first
if (i == 0 && ph.Item2 > 0)
regex_pattern.Append(Regex.Escape(
curpattern.Substring(0, ph.Item2)));
// Generate the capture for the placeholder
regex_pattern.AppendFormat("(?<{0}>.*?)",
ph.Item1.Replace("%", ""));
// The literal after the placeholder
if (i + 1 == cur_placeholders.Count)
regex_pattern.Append(Regex.Escape(
curpattern.Substring(ph.Item2 + ph.Item3)));
else
regex_pattern.Append(Regex.Escape(
curpattern.Substring(ph.Item2 + ph.Item3,
cur_placeholders[i + 1].Item2 - (ph.Item2 + ph.Item3))));
}
regex_pattern.Append('$');
var re = new Regex(regex_pattern.ToString());
foreach (var pathname in Directory.EnumerateFileSystemEntries(path))
{
var file = Path.GetFileName(pathname);
var m = re.Match(file);
if (!m.Success)
continue;
// New name is initially same as target pattern
var newname = newpattern;
// Iterate through the placeholder names
for (var i = new_placeholders.Count; i > 0; --i)
{
// Target placeholder name
var tn = new_placeholders[i-1].Item1.Replace("%", "");
// Get captured value for this capture
var ct = m.Groups[tn].Value;
// Perform the replacement
newname = newname.Remove(new_placeholders[i - 1].Item2,
new_placeholders[i - 1].Item3);
newname = newname.Insert(new_placeholders[i - 1].Item2, ct);
}
newname = Path.Combine(path, newname);
yield return new Tuple<string, string>(pathname, newname);
}
}
}
}
Make the regex pattern %(?<name>[^%]+)%. This will capture you all tokens in the string that are surrounded by percent signs.
Then, use Regex.Replace to replace them:
var replaced = Regex.Replace(input, pattern, (Match m) => EvaluateToken(m.Groups["name"].Value));
Regex.Replace can take a callback that allows you to provide a dynamic value.
can somebody help me to match following type of strings "BEREŽALINS", "GŽIBOVSKIS" in C# and js , I've tried
\A\w+\z (?>\P{M}\p{M}*)+ ^[-a-zA-Z\p{L}']{2,50}$
, and so on ... but nothing works .
Thanks
Just wrote a little console app to do it:
private static void Main(string[] args) {
var list = new List<string> {
"BEREŽALINS",
"GŽIBOVSKIS",
"TEST"
};
var pat = new Regex(#"[^\u0000-\u007F]");
foreach (var name in list) {
Console.WriteLine(string.Concat(name, " = ", pat.IsMatch(name) ? "Match" : "Not a Match"));
}
Console.ReadLine();
}
Works with the two examples you gave me, but not sure about all scenarios :)
Can you give an example of what is should not match?
Reading your question it's like you want to match just string (on seperates line maybe). If thats the case just use
^.*$
In C# this becomes
foundMatch = Regex.IsMatch(SubjectString, "^.*$", RegexOptions.Multiline);
And in javascript this is
if (/^.*$/m.test(subject)) {
// Successful match
} else {
// Match attempt failed
}