I have a string with a number at the end, after a dash ("-"). I'd like to create that same string with that number incremented by 1. Pretty simple, but I'm wondering if there's a better approach to this? Thanks!
string oldString = "BA-0001-3";
int lastIndex = oldString.LastIndexOf("-");
string oldNumber = oldString.SubString(lastIndex + 1);
string oldPartialString = oldString.SubString(0, lastIndex);
int newNumber = Convert.ToInt32(oldNumber) + 1;
string newString = oldPartialString + newNumber.ToString();
Regex?
Example:
Regex.Replace("BA-0001-3", #"[A-Z]{2}-\d{4}-(\d+)",
m => (Convert.ToInt32(m.Groups[1].Value) + 1).ToString())
I would probably use my friend string.Split:
string oldString = "BA-0001-3";
string[] parts = oldString.Split('-');
parts[parts.Length-1] = (Convert.ToInt32(parts[parts.Length-1])+1).ToString();
string newString = string.Join("-", parts);
A small tweak that will perhaps make it quicker (by accessing parts.Length and subtracting 1 only once - didn't profile so it's purely a guess, and it is likely a marginal difference anyway), but above all more robust (by using int.TryParse):
string oldString = "BA-0001-3";
string[] parts = oldString.Split('-');
int number;
int lastIndex = parts.Length-1;
parts[lastIndex] = (int.TryParse(parts[lastIndex], out number) ? ++number : 1).ToString();
string newString = string.Join("-", parts);
Updated per Ahmad Mageed's comments below. This is his answer much more than it is mine now :-)
I would do it the way you have it now, but for fun wanted to see if I could do it with linq.
var x = "BA-0001-3".Split('-');
var y = x.First() + "-" + x.ElementAt(1) + "-" + (Convert.ToInt32(x.Last()) + 1);
This works in LINQPad.
Edit: Obviously I'm not a pro with linq. Hopefully there will be other answers/comments on how this can be improved.
Here's an example of how it could be done with RegEx:
public void Test()
{
System.Text.RegularExpressions.Regex rx = new Regex(#"(?<prefix>.*\-)(?<digit>\d+)");
string input = "BA-0001-3";
string output = string.Empty;
int digit = 0;
if (int.TryParse(rx.Replace(input, "${digit}"), out digit))
{
output = rx.Replace(input, "${prefix}" + (digit + 1));
}
Console.WriteLine(output);
}
Using the regex (which already seems to have now been filled in with more details) I end up with something like:
var regex = new Regex(#"^(?<Category>[A-Za-z]{1,2})-(?<Code>[0-9]{4})-(?<Number>[0-9]+)$");
var newCode = regex.Replace("BA-0001-3", new MatchEvaluator(ReplaceWithIncrementedNumber));
Where the MatchEvaluator function is:
public static string ReplaceWithIncrementedNumber(Match match)
{
Debug.Assert(match.Success);
var number = Int32.Parse(match.Groups["Number"].Value);
return String.Format("{0}-{1}-{2}", match.Groups["Category"].Value, match.Groups["Code"].Value, number + 1);
}
Here is an example of a class that exposes the three parts of your "part number". Not particularly fancy (also note the absence of error checking/validation).
class Program
{
static void Main(string[] args)
{
PartNumber p1 = new PartNumber("BA-0001-3");
for (int i = 0; i < 5; i++)
{
p1.Sub++;
Debug.WriteLine(p1);
}
PartNumber p2 = new PartNumber("BA", 2, 3);
for (int i = 0; i < 5; i++)
{
p2.Sub++;
Debug.WriteLine(p2);
}
}
}
class PartNumber
{
public PartNumber(string make, int model, int sub)
{
Make = make;
Model = model;
Sub = sub;
}
public PartNumber(string part)
{
//Might want to validate the string here
string [] fields = part.Split('-');
//Are there 3 fields? Are second and third fields valid ints?
Make = fields[0];
Model = Int32.Parse(fields[1]);
Sub = Int32.Parse(fields[2]);
}
public string Make { get; set; }
public int Model { get; set; }
public int Sub { get; set; }
public override string ToString()
{
return string.Format("{0}-{1:D4}-{2}", Make, Model, Sub);
}
}
Related
The string (aka Message) I am trying to parse out looks like this. (It also looks exactly like this when you paste it in Notepad
"CorrelationId: b99fb632-78cf-4910-ab23-4f69833ed2d9
Request for API: /api/acmsxdsreader/readpolicyfrompolicyassignment Caller:C2F023C52E2148C9C1D040FBFAC113D463A368B1 CorrelationId: b99fb632-78cf-4910-ab23-4f69833ed2d9 RequestedSchemas: {urn:schema:Microsoft.Rtc.Management.Policy.Voice.2008}VoicePolicy, {urn:schema:Microsoft.Rtc.Management.Policy.Voice.2008}OnlineVoiceRoutingPolicy, TenantId: 7a205197-8e59-487d-b9fa-3fc1b108f1e5"
I would like to make 5 separate functions that return each of the specific values which would be like GetCorrelationId, GetRFAPI, GetCaller, GetRqSchema, and GetTenantId and extract out their corresponding values.
How would I do this in C# without using Regex?
Below is the code I have made for the caller (and this method is the same for all other 4 functions) but I have been advised that regex is slow and should not be used by my mentor and the method I have below doesn't even work anyway. Also, my biggest problem with trying to use the regex is that there are multiple delimiters in the message like ',' ' ' and ': ' and ':'
string parseCaller(string message)
{
var pattern = #"Caller:(.*)";
var r = new Regex(pattern).Match(message);
var caller = r.Groups[1].Value;
return caller;
}
Expected result should be:
GetCorrelationId(message) RETURNS b99fb632-78cf-4910-ab23-4f69833ed2d9
GetRFAPI(message) RETURNS /api/acmsxdsreader/readpolicyfrompolicyassignment
GetRqSchema(message) RETURNS {urn:schema:Microsoft.Rtc.Management.Policy.Voice.2008}VoicePolicy, {urn:schema:Microsoft.Rtc.Management.Policy.Voice.2008}OnlineVoiceRoutingPolicy
GetCaller(message) RETURNS C2F023C52E2148C9C1D040FBFAC113D463A368B1
GetTenantId(message) RETURNS 7a205197-8e59-487d-b9fa-3fc1b108f1e5
I would approach this a little differently and create a class that has properties for each value you want to parse from the string. Then we can create a static Parse method that creates an instance of the class from an input string, which sets all the properties for you.
If the string always has the same items (CorrelationId, RequestForAPI, Caller, etc) in the same order, we can utilize a simple helper method to GetValueBetween two headers.
The code is pretty simple:
class MessageData
{
public string CorrelationId { get; set; }
public string RequestForAPI { get; set; }
public string RequestedSchemas { get; set; }
public string Caller { get; set; }
public string TennantId { get; set; }
public static MessageData Parse(string input)
{
return new MessageData
{
CorrelationId = GetValueBetween(input, "CorrelationId:", "Request for API:"),
RequestForAPI = GetValueBetween(input, "Request for API:", "Caller:"),
Caller = GetValueBetween(input, "Caller:", "CorrelationId:"),
RequestedSchemas = GetValueBetween(input, "RequestedSchemas:", "TenantId:"),
TennantId = GetValueBetween(input, "TenantId:", null),
};
}
private static string GetValueBetween(string input, string startDelim, string endDelim)
{
if (input == null) return string.Empty;
var start = input.IndexOf(startDelim);
if (start == -1) return string.Empty;
start += startDelim.Length;
var length = endDelim == null
? input.Length - start
: input.IndexOf(endDelim, start) - start;
if (length < 0) length = input.Length - start;
return input.Substring(start, length).Trim();
}
}
And now we can just call MessageData.Parse(inputString), and we have a class with all it's properties set from the input string:
private static void Main()
{
var message = #"CorrelationId: b99fb632-78cf-4910-ab23-4f69833ed2d9
Request for API: /api/acmsxdsreader/readpolicyfrompolicyassignment Caller:C2F023C52E2148C9C1D040FBFAC113D463A368B1 CorrelationId: b99fb632-78cf-4910-ab23-4f69833ed2d9 RequestedSchemas: {urn:schema:Microsoft.Rtc.Management.Policy.Voice.2008}VoicePolicy, {urn:schema:Microsoft.Rtc.Management.Policy.Voice.2008}OnlineVoiceRoutingPolicy, TenantId: 7a205197-8e59-487d-b9fa-3fc1b108f1e5";
var messageData = MessageData.Parse(message);
// Now we can access any property
Console.WriteLine(messageData.CorrelationId);
Console.WriteLine(messageData.RequestForAPI);
Console.WriteLine(messageData.RequestedSchemas);
Console.WriteLine(messageData.Caller);
Console.WriteLine(messageData.TennantId);
Console.ReadKey();
}
Based on these specifications in your question:
How would I do this in C# without using Regex?
and
I would like to make 5 separate functions
You can try the below. It's really simple, as you can study your string and use IndexOf and SubString functions appropriately:
using System;
class ParseTest
{
static string GetCorrelationId(string message)
{
int i = message.IndexOf(": ") + 2; //length of ": "
int j = message.IndexOf("Request");
return message.Substring(i, j-i).Trim();
}
static string GetRFAPI(string message)
{
int i = message.IndexOf("API: ") + 5; //length of "API: "
int j = message.IndexOf("Caller");
return message.Substring(i, j-i).Trim();
}
static string GetCaller(string message)
{
int i = message.IndexOf("Caller:") + 7; //length of "Caller: "
int j = message.IndexOf(" CorrelationId");
return message.Substring(i, j-i).Trim();
}
static string GetRqSchema(string message)
{
int i = message.IndexOf("RequestedSchemas:") + 17; //length of "RequestedSchemas:"
int j = message.IndexOf(", TenantId:");
return message.Substring(i, j-i).Trim();
}
static string GetTenantId(string message)
{
int i = message.IndexOf("TenantId:") + 9; //length of "TenantId: "
return message.Substring(i).Trim();
}
static void Main()
{
string m = #"CorrelationId: b99fb632-78cf-4910-ab23-4f69833ed2d9
Request for API: /api/acmsxdsreader/readpolicyfrompolicyassignment Caller:C2F023C52E2148C9C1D040FBFAC113D463A368B1 CorrelationId: b99fb632-78cf-4910-ab23-4f69833ed2d9 RequestedSchemas: {urn:schema:Microsoft.Rtc.Management.Policy.Voice.2008}VoicePolicy, {urn:schema:Microsoft.Rtc.Management.Policy.Voice.2008}OnlineVoiceRoutingPolicy, TenantId: 7a205197-8e59-487d-b9fa-3fc1b108f1e5";
Console.WriteLine(GetCorrelationId(m));
Console.WriteLine(GetRFAPI(m));
Console.WriteLine(GetCaller(m));
Console.WriteLine(GetRqSchema(m));
Console.WriteLine(GetTenantId(m));
}
}
You can run it here.
EDIT: Of course you can modify this to use get-only properties, as some other answerers have tried to do.
If, on the other hand, you want to write a parser (this is kind of lazy one 😂), then that's another matter for your researching pleasure.
Here's a more robust solution if you don't know if the order of these elements returned from the API will change in the future:
private string GetRFAPI(string str)
{
return GetSubstring(str, "Request for API: ", ' ', 1);
}
private string GetCaller(string str)
{
return GetSubstring(str, "Caller:", ' ', 1);
}
private string GetCorrelationId(string str)
{
return GetSubstring(str, "CorrelationId: ", ' ', 1);
}
private string GetTenantId(string str)
{
return GetSubstring(str, "TenantId: ", ' ', 1);
}
private string GetRequestedSchemas(string str)
{
return GetSubstring(str, "RequestedSchemas: ", ',', 2);
}
private string GetSubstring(string str, string pattern, char delimiter, int occurrence)
{
int start = str.IndexOf(pattern);
if (start < 0)
{
return null;
}
for (int i = start + pattern.Length, counter = 0; i < str.Length; i++, counter++)
{
if ((str[i] == delimiter && --occurrence == 0) || i == str.Length - 1)
{
return str.Substring(start + pattern.Length, counter).Trim();
}
}
return null;
}
I wonder what would be the best way to format numbers so that the NumberGroupSeparator would work not only on the integer part to the left of the comma, but also on the fractional part, on the right of the comma.
Math.PI.ToString("###,###,##0.0##,###,###,###") // As documented ..
// ..this doesn't work
3.14159265358979 // result
3.141,592,653,589,79 // desired result
As documented on MSDN the NumberGroupSeparator works only to the left of the comma. I wonder why??
A little clunky, and it won't work for scientific numbers but here is a try:
class Program
{
static void Main(string[] args)
{
var π=Math.PI*10000;
Debug.WriteLine(Display(Ï€));
// 31,415.926,535,897,931,899
}
static string Display(double x)
{
int s=Math.Sign(x);
x=Math.Abs(x);
StringBuilder text=new StringBuilder();
var y=Math.Truncate(x);
text.Append((s*y).ToString("#,#"));
x-=y;
if (x>0)
{
// 15 decimal places is max reasonable precision
y=Math.Truncate(x*Math.Pow(10, 15));
text.Append(".");
text.Append(y.ToString("#,#").TrimEnd('0'));
}
return text.ToString();
}
}
It might be best to work with the string generated by your .ToString():
class Program
{
static string InsertSeparators(string s)
{
string decSeparator = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator;
int separatorPos = s.IndexOf(decSeparator);
if (separatorPos >= 0)
{
string decPart = s.Substring(separatorPos + decSeparator.Length);
// split the string into parts of 3 or less characters
List<String> parts = new List<String>();
for (int i = 0; i < decPart.Length; i += 3)
{
string part = "";
for (int j = 0; (j < 3) && (i + j < decPart.Length); j++)
{
part += decPart[i + j];
}
parts.Add(part);
}
string groupSeparator = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberGroupSeparator;
s = s.Substring(0, separatorPos) + decSeparator + String.Join(groupSeparator, parts);
}
return s;
}
static void Main(string[] args)
{
for (int n = 0; n < 15; n++)
{
string s = Math.PI.ToString("0." + new string('#', n));
Console.WriteLine(InsertSeparators(s));
}
Console.ReadLine();
}
}
Outputs:
3
3.1
3.14
3.142
3.141,6
3.141,59
3.141,593
3.141,592,7
3.141,592,65
3.141,592,654
3.141,592,653,6
3.141,592,653,59
3.141,592,653,59
3.141,592,653,589,8
3.141,592,653,589,79
OK, not my strong side, but I guess this may be my best bet:
string input = Math.PI.ToString();
string decSeparator = System.Threading.Thread.CurrentThread
.CurrentCulture.NumberFormat.NumberGroupSeparator;
Regex RX = new Regex(#"([0-9]{3})");
string result = RX.Replace(input , #"$1" + decSeparator);
Thanks for listening..
I wonder what would be the best way to format numbers so that the NumberGroupSeparator would work not only on the integer part to the left of the comma, but also on the fractional part, on the right of the comma.
Math.PI.ToString("###,###,##0.0##,###,###,###") // As documented ..
// ..this doesn't work
3.14159265358979 // result
3.141,592,653,589,79 // desired result
As documented on MSDN the NumberGroupSeparator works only to the left of the comma. I wonder why??
A little clunky, and it won't work for scientific numbers but here is a try:
class Program
{
static void Main(string[] args)
{
var π=Math.PI*10000;
Debug.WriteLine(Display(Ï€));
// 31,415.926,535,897,931,899
}
static string Display(double x)
{
int s=Math.Sign(x);
x=Math.Abs(x);
StringBuilder text=new StringBuilder();
var y=Math.Truncate(x);
text.Append((s*y).ToString("#,#"));
x-=y;
if (x>0)
{
// 15 decimal places is max reasonable precision
y=Math.Truncate(x*Math.Pow(10, 15));
text.Append(".");
text.Append(y.ToString("#,#").TrimEnd('0'));
}
return text.ToString();
}
}
It might be best to work with the string generated by your .ToString():
class Program
{
static string InsertSeparators(string s)
{
string decSeparator = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator;
int separatorPos = s.IndexOf(decSeparator);
if (separatorPos >= 0)
{
string decPart = s.Substring(separatorPos + decSeparator.Length);
// split the string into parts of 3 or less characters
List<String> parts = new List<String>();
for (int i = 0; i < decPart.Length; i += 3)
{
string part = "";
for (int j = 0; (j < 3) && (i + j < decPart.Length); j++)
{
part += decPart[i + j];
}
parts.Add(part);
}
string groupSeparator = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberGroupSeparator;
s = s.Substring(0, separatorPos) + decSeparator + String.Join(groupSeparator, parts);
}
return s;
}
static void Main(string[] args)
{
for (int n = 0; n < 15; n++)
{
string s = Math.PI.ToString("0." + new string('#', n));
Console.WriteLine(InsertSeparators(s));
}
Console.ReadLine();
}
}
Outputs:
3
3.1
3.14
3.142
3.141,6
3.141,59
3.141,593
3.141,592,7
3.141,592,65
3.141,592,654
3.141,592,653,6
3.141,592,653,59
3.141,592,653,59
3.141,592,653,589,8
3.141,592,653,589,79
OK, not my strong side, but I guess this may be my best bet:
string input = Math.PI.ToString();
string decSeparator = System.Threading.Thread.CurrentThread
.CurrentCulture.NumberFormat.NumberGroupSeparator;
Regex RX = new Regex(#"([0-9]{3})");
string result = RX.Replace(input , #"$1" + decSeparator);
Thanks for listening..
I am dynamically editing a regex for matching text in a pdf, which can contain hyphenation at the end of some lines.
Example:
Source string:
"consecuti?vely"
Replace rules:
.Replace("cuti?",#"cuti?(-\s+)?")
.Replace("con",#"con(-\s+)?")
.Replace("consecu",#"consecu(-\s+)?")
Desired output:
"con(-\s+)?secu(-\s+)?ti?(-\s+)?vely"
The replace rules are built dynamically, this is just an example which causes problems.
Whats the best solution to perform such a multiple replace, which will produce the desired output?
So far I thought about using Regex.Replace and zipping the word to replace with optional (-\s+)? between each character, but that would not work, because the word to replace already contains special-meaning characters in regex context.
EDIT: My current code, doesnt work when replace rules overlap like in example above
private string ModifyRegexToAcceptHyphensOfCurrentPage(string regex, int searchedPage)
{
var originalTextOfThePage = mPagesNotModified[searchedPage];
var hyphenatedParts = Regex.Matches(originalTextOfThePage, #"\w+\-\s");
for (int i = 0; i < hyphenatedParts.Count; i++)
{
var partBeforeHyphen = String.Concat(hyphenatedParts[i].Value.TakeWhile(c => c != '-'));
regex = regex.Replace(partBeforeHyphen, partBeforeHyphen + #"(-\s+)?");
}
return regex;
}
the output of this program is "con(-\s+)?secu(-\s+)?ti?(-\s+)?vely";
and as I understand your problem, my code can completely solve your problem.
class Program
{
class somefields
{
public string first;
public string secound;
public string Add;
public int index;
public somefields(string F, string S)
{
first = F;
secound = S;
}
}
static void Main(string[] args)
{
//declaring output
string input = "consecuti?vely";
List<somefields> rules=new List<somefields>();
//declaring rules
rules.Add(new somefields("cuti?",#"cuti?(-\s+)?"));
rules.Add(new somefields("con",#"con(-\s+)?"));
rules.Add(new somefields("consecu",#"consecu(-\s+)?"));
// finding the string which must be added to output string and index of that
foreach (var rul in rules)
{
var index=input.IndexOf(rul.first);
if (index != -1)
{
var add = rul.secound.Remove(0,rul.first.Count());
rul.Add = add;
rul.index = index+rul.first.Count();
}
}
// sort rules by index
for (int i = 0; i < rules.Count(); i++)
{
for (int j = i + 1; j < rules.Count(); j++)
{
if (rules[i].index > rules[j].index)
{
somefields temp;
temp = rules[i];
rules[i] = rules[j];
rules[j] = temp;
}
}
}
string output = input.ToString();
int k=0;
foreach(var rul in rules)
{
if (rul.index != -1)
{
output = output.Insert(k + rul.index, rul.Add);
k += rul.Add.Length;
}
}
System.Console.WriteLine(output);
System.Console.ReadLine();
}
}
You should probably write your own parser, it's probably easier to maintain :).
Maybe you could add "special characters" around pattern in order to protect them like "##" if the strings not contains it.
Try this one:
var final = Regex.Replace(originalTextOfThePage, #"(\w+)(?:\-[\s\r\n]*)?", "$1");
I had to give up an easy solution and did the editing of the regex myself. As a side effect, the new approach goes only twice trough the string.
private string ModifyRegexToAcceptHyphensOfCurrentPage(string regex, int searchedPage)
{
var indexesToInsertPossibleHyphenation = GetPossibleHyphenPositions(regex, searchedPage);
var hyphenationToken = #"(-\s+)?";
return InsertStringTokenInAllPositions(regex, indexesToInsertPossibleHyphenation, hyphenationToken);
}
private static string InsertStringTokenInAllPositions(string sourceString, List<int> insertionIndexes, string insertionToken)
{
if (insertionIndexes == null || string.IsNullOrEmpty(insertionToken)) return sourceString;
var sb = new StringBuilder(sourceString.Length + insertionIndexes.Count * insertionToken.Length);
var linkedInsertionPositions = new LinkedList<int>(insertionIndexes.Distinct().OrderBy(x => x));
for (int i = 0; i < sourceString.Length; i++)
{
if (!linkedInsertionPositions.Any())
{
sb.Append(sourceString.Substring(i));
break;
}
if (i == linkedInsertionPositions.First.Value)
{
sb.Append(insertionToken);
}
if (i >= linkedInsertionPositions.First.Value)
{
linkedInsertionPositions.RemoveFirst();
}
sb.Append(sourceString[i]);
}
return sb.ToString();
}
private List<int> GetPossibleHyphenPositions(string regex, int searchedPage)
{
var originalTextOfThePage = mPagesNotModified[searchedPage];
var hyphenatedParts = Regex.Matches(originalTextOfThePage, #"\w+\-\s");
var indexesToInsertPossibleHyphenation = new List<int>();
//....
// Aho-Corasick to find all occurences of all
//strings in "hyphenatedParts" in the "regex" string
// ....
return indexesToInsertPossibleHyphenation;
}
How can I delete the first n lines in a string?
Example:
String str = #"a
b
c
d
e";
String output = DeleteLines(str, 2)
//Output is "c
//d
//e"
You can use LINQ:
String str = #"a
b
c
d
e";
int n = 2;
string[] lines = str
.Split(Environment.NewLine.ToCharArray())
.Skip(n)
.ToArray();
string output = string.Join(Environment.NewLine, lines);
// Output is
// "c
// d
// e"
If you need to take into account "\r\n" and "\r" and "\n" it's better to use the following regex:
public static class StringExtensions
{
public static string RemoveFirstLines(string text, int linesCount)
{
var lines = Regex.Split(text, "\r\n|\r|\n").Skip(linesCount);
return string.Join(Environment.NewLine, lines.ToArray());
}
}
Here are some more details about splitting text into lines.
Combination of Get the index of the nth occurrence of a string? (search for Environment.NewLine) and substring should do the trick.
Try the following:
public static string DeleteLines(string s, int linesToRemove)
{
return s.Split(Environment.NewLine.ToCharArray(),
linesToRemove + 1
).Skip(linesToRemove)
.FirstOrDefault();
}
the next example:
string str = #"a
b
c
d
e";
string output = DeleteLines(str, 2);
returns
c
d
e
Try this:
public static string DeleteLines (string text, int lineCount) {
while (text.Split('\n').Length > lineCount)
text = text.Remove(0, text.Split('\n')[0].Length + 1);
return text;
}
It might not be very efficient but it works perfectly for the little project i've been working on recently
Try the following:
private static string DeleteLines(string input, int lines)
{
var result = input;
for(var i = 0; i < lines; i++)
{
var idx = result.IndexOf('\n');
if (idx < 0)
{
// do what you want when there are less than the required lines
return string.Empty;
}
result = result.Substring(idx+1);
}
return result;
}
Note: This method is not ideal for extremely long multi-line strings as it does not consider memory management. If dealing with these kind of strings, I suggest you alter the method to use the StringBuilder class.
With ability to delete first n lines or last n lines:
public static string DeleteLines(
string stringToRemoveLinesFrom,
int numberOfLinesToRemove,
bool startFromBottom = false) {
string toReturn = "";
string[] allLines = stringToRemoveLinesFrom.Split(
separator: Environment.NewLine.ToCharArray(),
options: StringSplitOptions.RemoveEmptyEntries);
if (startFromBottom)
toReturn = String.Join(Environment.NewLine, allLines.Take(allLines.Length - numberOfLinesToRemove));
else
toReturn = String.Join(Environment.NewLine, allLines.Skip(numberOfLinesToRemove));
return toReturn;
}
public static string DeleteLines(string input, int linesToSkip)
{
int startIndex = 0;
for (int i = 0; i < linesToSkip; ++i)
startIndex = input.IndexOf('\n', startIndex) + 1;
return input.Substring(startIndex);
}