I have a string s which reads my batch file content.
Suppose the content of s is as follows:
"\t\r\n##echo off\r\necho \"Hello World!!!\"\r\necho \"One\"\r\nset /p DUMMY=Hit ENTER to continue...\r\ncall second.bat\r\necho \"done!!!\"\r\ncall third.bat\r\necho \"done 3!!!\""
i want to write a condition which does the below,
while (s.Contains("call")) && (if string next to "call" contains(.bat))
how to acheive this?
I am new to c#. Please help me in this regard.
thanks in advance
You can split the string on new lines and process only the lines you want as follows:
foreach (string line in s.Split("\r\n", StringSplitOptions.None).Where(x => x.ToLower().StartsWith("call") && x.ToLower().EndsWith(".bat")))
{
// do stuff here
}
It seems that you are parsing some kind of log; in this case I suggest using regular expressions, e.g.
using System.Text.RegularExpressions;
...
string source =
"\t\r\n##echo off\r\necho \"Hello World!!!\"\r\necho \"One\"\r\nset /p DUMMY=Hit ENTER to continue...\r\ncall second.bat\r\necho \"done!!!\"\r\ncall third.bat\r\necho \"done 3!!!\"";
var matches = Regex
.Matches(source, #"call.+?\.bat", RegexOptions.IgnoreCase)
.OfType<Match>()
.Select(match => match.Value);
// call second.bat
// call third.bat
foreach (string match in matches) {
...
}
It's unclear what is "string next", in the code above I've treated it as "after". In case it means "after several white spaces" the pattern will be
.Matches(source, #"call\s+?\.bat", RegexOptions.IgnoreCase)
The first thing that comes to my mind is using the text.Split ('\n', '\r') method. This way you get an array of strings which are separated by those line break symbols. Because you'd get empty strings, you should also filter those out. For that, I would recommend converting the array to a list, iterate through all elements and remove all empty strings (consider using string.IsNullOrEmpty (text)).
If you always have \r\n, you can use text.Split("\r\n", StringSplitOptions.None) instead, and don't have to worry about empty strings in between. You could still convert it to a list for easier use.
Then you would get a fine list of the entire content separated through line breaks. Now you could loop through that and do whatever you want.
Related
I'm looking for a regex in C#.net to extract printers from a list in a script.
This is an example:
#set nr=2
#if not exist "%userprofile%\Version%nr%.txt" goto reload
#goto koppla
:reload
#echo skrivare>"%userprofile%\Version%nr%.txt"
#del "%userprofile%\zxy-*.txt"
#call skrivare.cmd
#exit
:koppla
#%connect1% \\%Print2%\Lund-M1
#%connect2% \\%Print2%\MAR-M1
#%connect2% \\%Print2%\MAR-M2
I would like to get the names (Lund-M1, MAR-M1, MAR-M2) of the printers in a array to foreach.
I really appreciate any help on this, my mind doesn't work with Regex.
Thank you in advance!
You could do something quite simple, like searching for the Print2 prefix:
\\\\%Print2%\\(.*)
This gives the following output on http://www.regexer.com. You'd then need to access the first group of each Match object to grab the part of the string you are after.
Edit
If you want to encapsulate different print numbers use the following which allows the 2 to be exchanged with any other number.
\\\\%Print[0-9]%\\(.*)
(?m:(?<=^#\%connect\d\% \\\\(.*?\\)*)[^\\]+$)
will give three matches over your script, with values
Lund-M1
MAR-M1
MAR-M2
So
Regex.Matches(input, #"(?m:(?<=^#\%connect\d\% \\\\(.*?\\)*)[^\\]+$)")
.Cast<Match>()
.Select(m => m.Value)
.ToArray()
gives you what you need.
This checks for line starting #%connect then any digit followed by % then pulls the last segment of any path of the form \\something\something\something\AnyNonBackslashChars
foreach (Match match in Regex.Matches(text,
#"^#%connect\d+%\s+\\\\%Print2%\\(.*?)\s*$", RegexOptions.IgnoreCase | RegexOptions.Multiline))
{
if (match.Success)
{
var name = match.Groups[1];
}
}
I am trying to replace a bunch of strings in files. The strings are stored in a datatable along with the new string value.
string contents = File.ReadAllText(file);
foreach (DataRow dr in FolderRenames.Rows)
{
contents = Regex.Replace(contents, dr["find"].ToString(), dr["replace"].ToString());
File.SetAttributes(file, FileAttributes.Normal);
File.WriteAllText(file, contents);
}
The strings look like this _-uUa, -_uU, _-Ha etc.
The problem that I am having is when for example this string "_uU" will also overwrite "_-uUa" so the replacement would look like "newvaluea"
Is there a way to tell regex to look at the next character after the found string and make sure it is not an alphanumeric character?
I hope it is clear what I am trying to do here.
Here is some sample data:
private function _-0iX(arg1:flash.events.Event):void
{
if (arg1.type == flash.events.Event.RESIZE)
{
if (this._-2GU)
{
this._-yu(this._-2GU);
}
}
return;
}
The next characters could be ;, (, ), dot, comma, space, :, etc.
First of all, you should use Regex.Escape.
You can use then
contents = Regex.Replace(
contents,
Regex.Escape(dr["find"].ToString()) + #"(?![a-zA-Z])",
Regex.Escape(dr["replace"].ToString()));
or even better
contents = Regex.Replace(
contents,
#"\b" + Regex.Escape(dr["find"].ToString()) + #"\b",
Regex.Escape(dr["replace"].ToString()));
I think this is what you're looking for:
contents = Regex.Replace(
contents,
string.Format(#"(?<!\w){0}(?!\w)", Regex.Escape(dr["find"].ToString())),
dr["replace"].ToString().Replace("$", "$$")
);
You can't use \b because your search strings don't always start and end with word characters. Instead, I used (?<!\w) and (?!\w) to make sure the matched substring is not immediately preceded or followed by a word character (i.e., a letter, a digit, or an underscore). I don't know the complete specs for your search strings, so this pattern might need some tweaking.
None of the sample patterns you provided contain regex metacharacters, but like the other responders, I used Regex.Escape() to render it safe anyway. In the replacement string the only character you have to watch out for is the dollar sign (ref), and the way to escape that is with another dollar sign. Notice that I used String.Replace() for that instead of Regex.Replace().
There are two tricks that can help you here:
Order all the search string by length, and replace the longest ones first, that way you won't accidentally replace the shorter ones.
Use a MatchEvaluator and instead of looping through all your rows, search fro all replacement patterns in the string and look them up in your dataset.
Option one is simple, option two would look like this:
Regex.Replace(contents", "_-\\w+", ReplaceIdentifier)
public string ReplaceIdentifier(Match m)
{
DataRow row = FolderRenames.Rows.FindRow("find"); // Requires a primary key on "find"
if (row != null) return row["replace"];
else return m.Value;
}
I have a multiline string (from a txt-file using ReadAllText).
the string looks like this:
R;0035709310000026542510X0715;;;
R;0035709310000045094410P1245;;;
R;0035709310000026502910Z1153;;;
I want to put in a ";" in each line on place 22, so it looks like this:
R;00357093100000265425;10X0715;;;
R;00357093100000450944;10P1245;;;
R;00357093100000265029;10Z1153;;;
The multiline string always contain the samme amount of data but not always 3 lines - sometimes more lines.
How do I make this? Please show some code.
Thanks alot :-)
Best regards
Bent
Try this ...
using System.IO;
using System.Linq;
var lines = File.ReadAllLines("data.txt");
var results = lines.Select(x => x.Insert(22, ";"));
Step 1, don't use ReadAllText(). Use ReadAllLines() instead.
string[] myLinesArray = File.ReadAllLines(...);
Step 2, replace all lines (strings) with the changed version.
for(int i = 0; i < myLinesArray.Length; i++)
myLinesArray[i] = myLinesArray[i].Insert(22, ";");
Step 3, Use WriteAllLines()
try this
string s ="R;0035709310000026542510X0715;;;";
s = s.Insert(22,";");
Console.Write(s);
or use Regex
string s =#"R;0035709310000026542510X0715;;;
R;0035709310000045094410P1245;;;
R;0035709310000026502910Z1153;;;";
string resultString = Regex.Replace(s, "^.{22}", "$0;", RegexOptions.IgnoreCase | RegexOptions.Multiline);
Console.Write(resultString);
I think it would be better to read the source file line by line and modify the line as you go.
You could build up your new file in a StringBuilder or, if is large,
write it to a new file, used to replace the source at the end.
Something like this,
using System.IO;
string tempFileName = Path.GetTempFileName();
using (StreamWriter target = File.CreateText(tempFileName))
{
using(StreamReader source = file.OpenText("YourSourceFile.???"))
{
while (source.Peek() >= 0)
{
target.WriteLine(source.ReadLine().Insert(22, ";"));
}
}
}
File.Delete("YourSourceFile.???");
File.Move(tempFileName, "YourSourceFile.???");
This approach becomes is especially appropriate for large files since it avoids loading all the data into memory at once but the performance will be good for all but very large files or, I guess, if the lines were very (very) long.
As suggested, you can use the Insert method to achieve your goal.
If your file contains a lot of lines and you need to work on 1 line at a time, you might also consider reading it line by line from a TextReader.
You could go with Regex:
myString = Regex.Replace(myString, #"(^.{22})", #"\1;", RegexOptions.Multiline);
Explanation:
you have 3 string arguments:
1st one is the input
2nd is the pattern
3rd is the replacement string
In the pattern:
() is a capturing group: you can call it in the replacement string with \n, n being the 1-based index of the capturing group in the pattern. In this case, \1 is whatever matched "(^.{22})"
"^" is the beginning of a line (because we set the multiline options, otherwise it would be the beginning of the input string)
"." matches any character
{22} means you want preceeding pattern (in this case ".", any character) 22 times
So what that means is:
"in any line with 22 characters or more, replace the 22 first characters by those same 22 characters plus ";"
I'm having the following string as an example:
<tr class="row_odd"><td>08:00</td><td>08:10</td><td>TEST1</td></tr><tr class="row_even"><td>08:10</td><td>08:15</td><td>TEST2</td></tr><tr class="row_odd"><td>08:15</td><td>08:20</td><td>TEST3</td></tr><tr class="row_even"><td>08:20</td><td>08:25</td><td>TEST4</td></tr><tr class="row_odd"><td>08:25</td><td>08:30</td><td>TEST5</td></tr>
I need to have to have the output as a onedimensional Array.
Like 11111=myArray(0) , 22222=myArray(1) , 33333=myArray(2) ,......
I have already tried the myString.replace, but it seems I can only replace a single Char that way. So I need to use expressions and a for loop for filling the array, but since this is my first c# project, that is a bridge too far for me.
Thanks,
It seems like you want to use a Regex search pattern. Then return the matches (using a named group) into an array.
var regex = new Regex("act=\?(<?Id>\d+)");
regex.Matches(input).Cast<Match>()
.Select(m => m.Groups["Id"])
.Where(g => g.Success)
.Select(g => Int32.Parse(g.Value))
.ToArray();
(PS. I'm not positive about the regex pattern - you should check into it yourself).
Several ways you could do this. A couple are:
a) Use a regular expression to look for what you want in the string. Used a named group so you can access the matches directly
http://www.regular-expressions.info/dotnet.html
b) Split the expression at the location where your substrings are (e.g. split on "act="). You'll have to do a bit more parsing to get what you want, but that won't be to difficult since it will be at the beginning of the split string (and your have other srings that dont have your substring in them)
Use a combination of IndexOf and Substring... something like this would work (not sure how much your string varies). This will probably be quicker than any Regex you come up with. Although, looking at the length of your string, it might not really be an issue.
public static List<string> GetList(string data)
{
data = data.Replace("\"", ""); // get rid of annoying "'s
string[] S = data.Split(new string[] { "act=" }, StringSplitOptions.None);
var results = new List<string>();
foreach (string s in S)
{
if (!s.Contains("<tr"))
{
string output = s.Substring(0, s.IndexOf(">"));
results.Add(output);
}
}
return results;
}
Split your string using HTML tags like "<tr>","</tr>","<td>","</td>", "<a>","</a>" with strinng-variable.split() function. This gives you list of array.
Split html row into string array
So I'm trying to match up a regex and I'm fairly new at this. I used a validator and it works when I paste the code but not when it's placed in the codebehind of a .NET2.0 C# page.
The offending code is supposed to be able to split on a single semi-colon but not on a double semi-colon. However, when I used the string
"entry;entry2;entry3;entry4;"
I get a nonsense array that contains empty values, the last letter of the previous entry, and the semi-colons themselves. The online javascript validator splits it correctly. Please help!
My regex:
((;;|[^;])+)
Split on the following regular expression:
(?<!;);(?!;)
It means match semicolons that are neither preceded nor succeeded by another semicolon.
For example, this code
var input = "entry;entry2;entry3;entry4;";
foreach (var s in Regex.Split(input, #"(?<!;);(?!;)"))
Console.WriteLine("[{0}]", s);
produces the following output:
[entry]
[entry2]
[entry3]
[entry4]
[]
The final empty field is a result of the semicolon on the end of the input.
If the semicolon is a terminator at the end of each field rather than a separator between consecutive fields, then use Regex.Matches instead
foreach (Match m in Regex.Matches(input, #"(.+?)(?<!;);(?!;)"))
Console.WriteLine("[{0}]", m.Groups[1].Value);
to get
[entry]
[entry2]
[entry3]
[entry4]
Why not use String.Split on the semicolon?
string sInput = "Entry1;entry2;entry3;entry4";
string[] sEntries = sInput.Split(';');
// Do what you have to do with the entries in the array...
Hope this helps,
Best regards,
Tom.
As tommieb75 wrote, you can use String.Split with StringSplitOptions Enumeration so you can control your output of newly created splitting array
string input = "entry1;;entry2;;;entry3;entry4;;";
char[] charSeparators = new char[] {';'};
// Split a string delimited by characters and return all non-empty elements.
result = input.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries);
The result would contain only 4 elements like this:
<entry1><entry2><entry3><entry4>