Extracting a number from a specific substring pattern - c#

SOLVED! Ended up using this to do what I wanted:
if (output.Contains("<%TABLE#"))
{
string pattern = #"<%TABLE#([0-9]+)%%>";
RegexOptions options = RegexOptions.Multiline;
foreach (Match m in Regex.Matches(output, pattern, options))
{
int objectID = Int32.Parse(Regex.Match(m.Value, #"\d+").Value);
output = output.Replace(m.Value, ConvertFunction(objectID));
}
}
In some parts of my SQL data (rendered by a C#/ASP.NET website front-end) are strings, many of which can contain a pattern like <%TABLE#[NUMBER]%%> - [NUMBER] is always a specific ID, 1+. An example in one string would look like <%TABLE#3%%>. Sometimes there may be more than one of these patterns in the same string. I am ultimately trying to do the following:
Find all instances in the string where the pattern occurs
For each instance, call another building function using the # that is present - it takes that # and produces a NewString
Replace that instance of the code with NewString
I do this because each of the SQL tables has a website page to show the data within to the end-user. The way I format the data differs from table to table, so I have a Class for each table that builds the output string and returns it where needed. Sometimes, I need to display an object from a different table within the current one. To try and solve this, I added the above formula within the string, in the specific spot I want the object to be rendered, in the hopes of identifying it and using the ID within to grab the appropriate object, build it, then replace that pattern.
I'm guessing I'll have to use Regex or something to identify the string, but I'm struggling on the best way to grab the pattern, identify the number within, call the function to render the output text using said number, and then replace that specific pattern with the results.
Below are some example inputs and what the output should be. The function ConvertFormula takes in an INT and outputs a STRING.
EXAMPLE INPUTS/EXPECTED OUTPUT
Example 1:
"Here's some data and more stuff.<%TABLE#3541%%>Here is more text.
<%TABLE#31214%%>And some more."
Output 1:
"Here's some data and more stuff." + ConvertFormula(3541) + "Here is more text." + ConvertFormula(31214) + "And some more."
Example 2:
"Here's some data and more stuff! Maybe more here!<%TABLE#2%%>Here is more text."
Output 2:
"Here's some data and more stuff! Maybe more here!" + ConvertFormula(2) + "Here is more text."
Example 3:
"<%TABLE#2%%>This is something completely different with the object call at the start.<TABLE#52%%> and another here."
Output 3:
ConvertFormula(2) + "This is something completely different with the object call at the start." + ConvertFormula(52) + " and another here."
Example 4:
"There's nothing in this one, no code to find. Just has some text."
Output 4:
"There's nothing in this one, no code to find. Just has some text."
Example 5:
"This one goes on for a while, like 5132854123 characters, then has a single call right here.<%TABLE#112%%>"
Output 5:
"This one goes on for a while, like 5132854123 characters, then has a single call right here." + ConvertFormula(112)
Example 6:
"Short <%TABLE#412%%> one."
Output 6:
"Short " + ConvertFormula(412) + " one."
Example 7:
"Nothing here again."
Output 7:
"Nothing here again."

I'm guessing that this expression might simply work,
<%TABLE#([0-9]+)%%>
which we would use a capturing group and collect our desired IDs.
Demo
Test
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = #"<%TABLE#([0-9]+)%%>";
string input = #"<%TABLE#3%%>
<%TABLE#1213%%>";
RegexOptions options = RegexOptions.Multiline;
foreach (Match m in Regex.Matches(input, pattern, options))
{
Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index);
}
}
}

Related

How to get data from each row of website (DownloadString) by after : char and stop till ; char

I use WebClient and DownloadString to get RAW text file into an string, and I would like to get the first words, like each thing before : char in to a string, AND also the stuff after : but before ; in other string. In this case I want word111 and floor271 in seperate string, and table123 and fan891 into an other string.
The text file looks like this:
word111:table123;
floor271:fan891;
I've tried to look around for days, because I use in my code the Contains method to see if the whole line of text sometimes matches, example word111:table123; if that exists in the raw text file, then the code continues. I looked at Split, IndexOf, and things like that but I don't understand if they can even achieve this goal, because I need them from every row/line, not just one.
WebClient HWIDReader = new WebClient();
string HWIDList = HWIDReader.DownloadString("/*the link would be here, can't share it*/");
if (HWIDList.Contains(usernameBox.Text + ":" + passwordBox.Text))
{
/* show other form because username and password did exist */
}
I expect the code wouldn't work with Split, because it can split the string by : and ; characters tho, but I don't want the usernames and passwords visible in the same string. IndexOf would delete before or after specified characters tho. (Maybe can use IndexOf to both ways? to remove from : till ; is that possible, and how?) Thank you in advance.
You can split the string based on the newline character.
string HWIDList = HWIDReader.DownloadString("/*the link would be here, can't share it*/");
string[] lines = HWIDList.Split('\n');
// NOTE: Should create a hash from the password and compare to saved password hashes
// so that nobody knows what the users' passwords are
string userInput = string.Format("{0}:{1};", usernameBox.Text, passwordBox.Text);
foreach (string pair in lines)
{
if (pair != userInput)
continue;
// found match: do stuff
}

After create or concat dynamic string how its execute and got data in place or data row filed

I will do work with asp.net C#. when I create runtime string (dynamic). After the string, I try to pass the data in the place of data row but I have no idea about that so please provide a proper solution.
Below is my code (code with example )
protected string Replace_Tag(string Email_msg)
{
try {
}
return Email_msg ;
}
After execute this function result found below. (return below string)
"View your all the details" + drmail["WorkName"].ToString() +
"this task is working " + drmail["Cjworkmode"].ToString() + "- " +
drmail["Cjtimeperiod"].ToString() + " "
This is the string so how can I execute this string in for loop and get the proper data.
For loop
string cast_data = Replace_Tag(EditorEmail.Content);
foreach (DataRow drmail in Get_Tab_Data().Tables[0].Rows)
{
String Vie_Data = cast_data;
}
In this for loop how to get below result.
View your all the details XYZ this task is working ABC - 2018
View your all the details ABC this task is working ABC - 2019
View your all the details EFG this task is working MZP - 2017
This is a principle called "string templating". Do some research to find existing solutions. If you don't want to use existing solutions, roll your own.
You could do so by introducing placeholders in the template string:
var templateString = "View all the details {WorkName} this task is working {Cjworkmode} - {Cjtimeperiod}";
Not to be confused with string interpolation, as these placeholders aren't known at compile time.
Then, for example using a regular expression, find all matches in the string:
var placeHolderRegEx = new Regex(#"(\{([a-z]+)\})", RegexOptions.IgnoreCase);
// Copy the string to be templated
var output = templateString;
foreach (Match match in placeHolderRegEx.Matches(templateString))
{
// Replace each instance of `{x}` with the value of `drmail[x]`.
output = output.Replace(match.Groups[1].Value, drmail[match.Groups[2].Value]);
}

Character ä is represented in different Char Codes in the same string

I have a on web uploaded File Name "Schränke Wintsch.pdf".
The file Name is saved in a XML file like so:
<File>Schra?nke Wintsch.pdf</File>
If I debug this in c# and maunally add an ä, then it is saved correctly.
<File>Schra?nke Wintsch-ä.pdf</File>
OK I know it is an Encoding Problem.
But why is the same ä character represented with different char codes(example on Img 2)?
XML defines the encoding used within the document using the header. It will look something like this.. <?xml version="1.0" encoding="ISO-8859-9" ?>.
If you append the string make sure to use the same encoding to avoid a mismatch.
Test appending the char bytes and see if that helps.
var en = Encoding.GetEncoding("ISO-8859-9");
en.GetString(Encoding.GetBytes("ä"));
The original XML that you have is using the Unicode 'COMBINING DIAERESIS' code (int value 776) to use two characters to representä.
(Note how the combining character has been displayed as ? in the <File>Schra?nke Wintsch.pdf</File> image in your post.)
The 776 code says to put the double-dots above the previous character (an a).
However, where you typed in the ä it has been stored as the unicode character with code 228.
The question you need to answer is: Why is the original source XML using the "Combining Diaeresis" character rather than the more usual ä? (Without knowing the origin of the XML file, we cannot answer that question.)
Incidentally, you can "normalise" those sorts of characters by using string.Normalize(), as demonstrated by the following program:
using System;
namespace Demo
{
static class Program
{
static void Main()
{
char[] a = {(char)97, (char)776};
string s = new string(a);
Console.WriteLine(s + " -> " + s.Length); // Prints a¨ -> 2
var t = s.Normalize();
Console.WriteLine(t + " -> " + t.Length); // Prints ä -> 1
}
}
}
Note how the length of s is 2, but the length of t is only 1 (and it contains the single character ä).
So you might be able to improve things by using string.Normalize() to normalise these unexpected characters.
string.Normalize() ist the working solution for the string "Schränke Wintsch-ä.pdf". So it ist correctly saved as Schränke Wintsch-ä.pdf

Is there an easy way to parse a structured text file in C#?

I'm trying to parse a text file, but I feel like there must be a better way to do it.
The text file is made up of items, which can contain both key value pairs as well as other items. I believe the file will only ever go as deep as a grandchild item (e.g. an item within an item, within an item).
Currently I'm iterating through the file line by line, and keeping track of the depth at which I am. Then once I reach a termination character ('}') and I'm at level 0, I know I've captured a whole parent item.
Since I don't think I've explained it well, my file structure will look similar to this.
parent_item {
key: value
key: value
child_item {
key: value
key: value
}
child_item {
key: value
key: value
key: value
grandchild_item {
key: value
key: value
}
}
key: value
key: value
}
parent_item {
key: value
key: value
child_item {
key: value
key: value
}
}
Each item can have 0 to many child items, though I don't think it will ever go deeper than 3 levels (parent -> child -> grandchild).
Is there an easier way to parse this, or am I working in the right direction?
Your file looks almost like JSON, except there are no colons between property names of a complex nested object. However, it is different enough that you won't be able to use a JSON parser like JSON.NET.
I recommend parsing it manually like you are doing-- but use a stack and state machine. Your state machine should push to the stack every time you encounter the open curly { and pop from the stack when you get the close curly }.
Being so similar to JSON, if the formatting is constant (open curly ´{´ and end curly } as the last character in the line) you could translate that text into JSON with minor changes. Warning, not tested, something like this:
StringBuilder jsonEncoded = new StringBuilder();
string[] lines = content.Split("\n");
foreach(string line in lines)
{
if(line.EndsWith("{") || line.EndsWith("}")
jsonEncoded.AppendLine(line);
else
jsonEncoded.AppendLine(line + ",");
}
After that, a regular JSON Deseralization would work.
If you can trust your source for not messing with this schema you can write a workaround. I have some ideas for you:
JSON
It looks like json. Maybe you can normalize it, then parse it with JSON.NET.
I just write a ugly but working solution. Try it here:
using System;
using System.Text.RegularExpressions;
public class Program
{
public static string Quoterize(string s)
{
return Regex.Replace(s, #"\w+", match => "\"" + match + "\"");
}
public static string RewriteThisPlease(string s)
{
return s
.Replace("\n", "," + Environment.NewLine)
.Replace(" ", "")
.Replace(Environment.NewLine, "")
.Replace("{,", "{")
.Replace(",}", "}");
}
public static void Main()
{
var k = #""; // your file goes here
Console.WriteLine("{"+MoveToRegexPlease(Quoterize((k).Replace("{", ": {")))+"}");
}
}
YAML
It looks like json. It looks even more like yaml. A yaml validator will accept your file after two simples replace:
// where k is your file as string
Console.WriteLine(k.Replace("{\n", ":\n").Replace("}",""));
Demo
Homemade
It looks like json. You will find a lot of JSON parser out there, maybe you can fork one and adapt it to works with your case.
Homework
It looks like json. You will find a lot of JSON parser tutorial out there. Writing a small parser is always a good exercise.
Good luck !
Here is a brief example (though not carefully tested yet) of using RegEx with Balancing Group Definitions
This example uses the code from the link. I just replaces the parentheses to not change the code and use it as it is:
static void Main(string[] args)
{
// here I read your posted file
string input = System.IO.File.ReadAllText("test.txt");
input = input.Replace('{', '<');
input = input.Replace('}', '>');
string pattern = "^[^<>]*" +
"(" +
"((?'Open'<)[^<>]*)+" +
"((?'Close-Open'>)[^<>]*)+" +
")*" +
"(?(Open)(?!))$";
//string input = "<abc><mno<xyz>>";
Match m = Regex.Match(input, pattern);
if (m.Success == true)
{
Console.WriteLine("Input: \"{0}\" \nMatch: \"{1}\"", input, m);
int grpCtr = 0;
foreach (Group grp in m.Groups)
{
Console.WriteLine(" Group {0}: {1}", grpCtr, grp.Value);
grpCtr++;
int capCtr = 0;
foreach (Capture cap in grp.Captures)
{
Console.WriteLine(" Capture {0}: {1}", capCtr, cap.Value);
capCtr++;
}
}
}
else
{
Console.WriteLine("Match failed.");
}
Console.ReadKey();
}
Copy paste this into a new console project, let it run and take a look at the output. It is confusing in the beginning, but it might give you a starter to adjust it to your needs.
Use Serialisation.
In C# you can easily use JSON or XML serialisation.
JSON:
https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx
A better way would be XML because it is more flexible and has a better support in C#:
https://msdn.microsoft.com/en-us/library/58a18dwa(v=vs.110).aspx

Adding a text stored in a variable to string to be saved to a text file

Hi I am trying to save text to a text file with some string, e.g. the students name added to it, but I'm a bit stuck
string iName2 = iName;
string text = "The student named {0} needs more work with plurals";
System.IO.File.WriteAllText(#"C:\Users\user\documents\visual studio 2012\Projects\Artificial_Intelligence_Project_3\WindowsFormsApplication1\Info.txt", text);`
I'm assuming iName is the name. String.Format is the method you need:
string text = String.Format("The student named {0} needs more work with plurals", iName);
Unless you need iName2 somewhere else, you do not need it.
Apart from being more readable, String.Format has one advantage over string concatenation with +. It allows you to change the order of substituted text fragments or omit some of them:
string text = String.Format("{0} {1}", a, b);
// changed order within text without changing argument order!
string text2 = String.Format("{1} {0}", a, b);
This is particularly useful if you're doing localization: Different languages have different rules to construct phrases, where the fragments may need to be substituted in different order.
string text = "The student named " + iName2 + " needs more work with plurals";

Categories

Resources