My string is like
COMMAND="HELP ME" TIMEOUT_SECONDS="30" APP_ID="SOMETHING RANDOM" COUNT="100" RETVAL="0" STDOUT="DATA I NEED" STDERR="NO ERROR" STATUS="SUCCESS"
I want to be able to extract STDOUT, STDERR and STATUS. How can I do it ?
You can try this regex:
(?<=(?:STDOUT|STDERR|STATUS)\=")([^"]+)
As a result you will get 3 results.
MatchCollection mcol = Regex.Matches(strInput, #“(?<=(?:STDOUT|STDERR|STATUS)\=")([^"]+)”);
foreach(Match m in mcol)
{
System.Diagnostic.Debug.Print(m.ToString());
}
Also:
using System.Text.RegularExpressions;
Live Demo
Here, in this part of regex:
(?:STDOUT|STDERR|STATUS)
You can also specify the key (other than the 3 mentioned) whose value is needed.
string input2 = #"COMMAND=""HELP ME"" TIMEOUT_SECONDS=""30"" APP_ID=""SOMETHING RANDOM"" COUNT=""100"" RETVAL=""0"" STDOUT=""DATA I NEED"" STDERR=""NO ERROR"" STATUS=""SUCCESS""";
var dict = Regex.Matches(input2, #"(.+?)=""(.+?)""").Cast<Match>()
.ToDictionary(m => m.Groups[1].Value.Trim(),
m => m.Groups[2].Value.Trim());
Console.WriteLine(dict["STDOUT"]);
Console.WriteLine(dict["STATUS"]);
Use the following function:
public static Dictionary<string,string> GetValues(string command)
{
Dictionary<string,string> output = new Dictionary<string,string>();
string[] splitCommand = command.Split(" ");
foreach(var item in splitCommand)
{
output.Add(item.Split("=")[0] , item.Split("=")[1]);
}
return output;
}
When you want to get the values use the function like
Dictionary<string,string> output = YourClass.GetValue(command);
string stdout = output["STDOUT"];
string etderr= output["ETDERR"];
string status = output["STATUS"];
I donot have access to compiler. So, there might be an error. But the overall functionality will look something like this.
Related
I am parsing a template file which will contain certain keys that I need to map values to. Take a line from the file for example:
Field InspectionStationID 3 {"PVA TePla #WSM#", "sw#data.tool_context.TOOL_SOFTWARE_VERSION#", "#data.context.TOOL_ENTITY#"}
I need to replace the string within the # symbols with values from a dictionary.
So there can be multiple keys from the dictionary. However, not all strings inside the # are in the dictionary so for those, I will have to replace them with empty string.
I cant seem to find a way to do this. And yes I have looked at this solution:
check if string contains dictionary Key -> remove key and add value
For now what I have is this (where I read from the template file line by line and then write to a different file):
string line = string.Empty;
var dict = new Dictionary<string, string>() {
{ "data.tool_context.TOOL_SOFTWARE_VERSION", "sw0.2.002" },
{"data.context.TOOL_ENTITY", "WSM102" }
};
StringBuilder inputText = new StringBuilder();
StreamWriter writeKlarf = new StreamWriter(klarfOutputNameActual);
using (StreamReader sr = new StreamReader(WSMTemplatePath))
{
while((line = sr.ReadLine()) != null)
{
//Console.WriteLine(line);
if (line.Contains("#"))
{
}
else
{
writeKlarf.WriteLine(line)
}
}
}
writeKlarf.Close();
THe idea is that for each line, replace the string within the # and the # with match values from the dictionary if the #string# is inside the dictionary. How can I do this?
Sample Output Given the line above:
Field InspectionStationID 3 {"PVA TePla", "sw0.2.002", "WSM102"}
Here because #WSM# is not the dictionary, it is replaced with empty string
One more thing, this logic only applies to the first qurter of the file. The rest of the file will have other data that will need to be entered via another logic so I am not sure if it makes sense to read the whole file in into memory just for the header section?
Here's a quick example that I wrote for you, hopefully this is what you're asking for.
This will let you have a <string, string> Dictionary, check for the Key inside of a delimiter, and if the text inside of the delimiter matches the Dictionary key, it will replace the text. It won't edit any of the inputted strings that don't have any matches.
If you want to delete the unmatched value instead of leaving it alone, replace the kvp.Value in the line.Replace() with String.Empty
var dict = new Dictionary<string, string>() {
{ "test", "cool test" }
};
string line = "#test# is now replaced.";
foreach (var kvp in dict)
{
string split = line.Split('#')[1];
if (split == kvp.Key)
{
line = line.Replace($"#{split}#", kvp.Value);
}
Console.WriteLine(line);
}
Console.ReadLine();
If you had a list of tuple that were the find and replace, you can read the file, replace each, and then rewrite the file
var frs = new List<(string F, string R)>(){
("#data.tool_context.TOOL_SOFTWARE_VERSION#", "sw0.2.002"),
("#otherfield#", "replacement here")
};
var i = File.ReadAllText("path");
frs.ForEach(fr => i = i.Replace(fr.F,fr.R));
File.WriteAllText("path2", i);
The choice to use a list vs dictionary is fairly arbitrary; List has a ForEach method but it could just as easily be a foreach loop on a dictionary. I included the ## in the find string because I got the impression the output is not supposed to contain ##..
This version leaves alone any template parameters that aren't available
You can try matching #...# keys with a help of regular expressions:
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
...
static string MyReplace(string value, IDictionary<string, string> subs) => Regex
.Replace(value, "#[^#]*#", match => subs.TryGetValue(
match.Value.Substring(1, match.Value.Length - 2), out var item) ? item : "");
then you can apply it to the file: we read file's lines, process them with a help of Linq and write them into another file.
var dict = new Dictionary<string, string>() {
{"data.tool_context.TOOL_SOFTWARE_VERSION", "sw0.2.002" },
{"data.context.TOOL_ENTITY", "WSM102" },
};
File.WriteAllLines(klarfOutputNameActual, File
.ReadLines(WSMTemplatePath)
.Select(line => MyReplace(line, dict)));
Edit: If you want to switch off MyReplace from some line on
bool doReplace = true;
File.WriteAllLines(klarfOutputNameActual, File
.ReadLines(WSMTemplatePath)
.Select(line => {
//TODO: having line check if we want to keep replacing
if (!doReplace || SomeCondition(line)) {
doReplace = false;
return line;
}
return MyReplace(line, dict)
}));
Here SomeCondition(line) returns true whenever header ends and we should not replace #..# any more.
I have pattern string:"Hello {Name}, welcome to {Country}"
and a full value string:"Hello Scott, welcome to VietNam"
How can I extract value of {Name} and {Country}:
Name = Scott, Country = VietNam
I have see some regular expression to resolve this problem but can I apply fuzzy matching here? e.g. With invert string "welcome to VietNam, Hello Scott", we must change the regular expression too?
You can use Regex:
var Matches = Regex.Matches(input, #"hello\s+?([^\s]*)\s*|welcome\s+?to\s+?([^\s]*)", RegexOptions.IgnoreCase);
string Name = Matches.Groups[1].Value;
string Country = Matches.Groups[2].Value;
Update: Changed code to work either way. Demo.
As a more general solution, you can do something like the following:
public Dictionary<string, string> GetMatches(string pattern, string source)
{
var tokens = new List<string>();
var matches = new Dictionary<string, string>();
pattern = Regex.Escape(pattern);
pattern = Regex.Replace(pattern, #"\\{.*?}", (match) =>
{
var name = match.Value.Substring(2, match.Value.Length - 3);
tokens.add(name);
return $"(?<{name}>.*)";
});
var sourceMatches = Regex.Matches(source, pattern);
foreach (var name in tokens)
{
matches[name] = sourceMatches[0].Groups[name].Value;
}
return matches;
}
The method extracts the token names from the pattern, then replaces the tokens with the equivalent syntax for a regular expression named capture group. Next, it uses the modified pattern as a regular expression to extract the values from the source string. Finally, it uses the captured token names with the named capture groups to build a dictionary to be returned.
Just quick and dirty..
string pattern = "Hello Scott, welcome to VietNam";
var splitsArray = pattern.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
var Name = splitsArray[1].Replace(",", string.Empty);
var country = splitsArray[4];
I have a string something like this:
<BU Name="xyz" SerialNo="3838383" impression="jdhfl87lkjh8937ljk" />
I want to extract values like this:
Name = xyz
SerialNo = 3838383
impression = jdhfl87lkjh8937ljk
How to get these values in C#?
I am using C# 3.5.
If by some reason you don't want to use Xml parser you can use reqular expression to achieve this.
Use this regular expression:
(\w)+=\"(\w)+\"
Use this regular expression like this:
var input = #"<BU Name=""xyz"" SerialNo=""3838383"" impression=""jdhfl87lkjh8937ljk"" />";
var pattern = #"(\w)+=\""(\w)+\""";
var result = Regex.Matches(input, pattern);
foreach (var match in result.Cast<Match>())
{
Console.WriteLine(match.Value);
}
Result:
//Name="xyz"
//SerialNo="3838383"
//impression="jdhfl87lkjh8937ljk"
//Press any key to continue.
hihi
i have a question that i want to ask about c# and window form
i have this data... A,B,C; A1,B1,C1; A2,B2,C2; (this data is not hardcoded, it can continue to change, when more data insert come in) , i select this database column which is name as ColABC , and i retrieve and put in the datagridview ,
So is possible to always get the middle data?....but it is always this format record1 data, record1 data, record1; record2 data, record3 data, record...and so i want this data all the middle value retrieve out to this become this B,B1,B2.......so on...
ID | ColABC
1 | A,B,C; A1,B1,C1; A2,B2,C2;
This is like my DataGridView, the above.
The only thing i know is use split by ; first then by ,.
Is there any direct way?
Something like this, I try:
string[] doll = null;
doll = Convert.ToString(DGV.CurrentRow.Cells[0].Value).Split(';');
Basically like example the above code, doll get the " A,B,C; A1,B1,C1; A2,B2,C2; " this data which i retrieve from datagridview, so if i declare roll[0] it will give me "A,B,C", like what i mention above the data will change so how am i get the middle value always??
var input = "A,B,C; A1,B1,C1; A2,B2,C2;";
var resultList = Regex.Matches(input, #".*?,(.*?),.*?;")
.Cast<Match>()
.Select(arg => arg.Groups[1].Value)
.ToList();
var firstValue = resultList[0];
var secondValue = resultList[1];
// bind to a combobox
comboBox1.DataSource = resultList;
var comaSeparatedString = string.Join(",", resultList);
string testString = "A,B,C; A1,B1,C1; A2,B2,C2;";
Regex rgx = new Regex("[^,]+,([^,]+),[^,]+");
List<string> whatYouWant = testString.Split(';').Select(a => rgx.Replace(a, "$1")).ToList();
or
string testString = "A,B,C; A1,B1,C1; A2,B2,C2;";
Regex rgx = new Regex("[^,;]+,([^,;]+),[^,;]+;?");
for(Match m = rgx.Match(testString); m.Success; m = m.NextMatch())
{
Console.WriteLine(m.Groups[1].Value);
}
What about this.... Not in my device, to test this code... Still this is the approach...
foreach(DataGridViewRow dgvr in Datagridview.Rows){
if(dgvr!=null){
string middlevalues="";
string testString= dgvr.Cells[ColumnIndex].Value.ToString();
//If this string is string testString = "A,B,C; A1,B1,C1; A2,B2,C2;";
string[] basesplit = testString.Split(';');
int i=0;
foreach(string words in baseplit){
if(i<baseplit.Count-1){
middlevalues=words.Split(',')[1].ToString()+','
}else{ middlevalues=words.Split(',')[1].ToString();
i++;
}
}
}
}
I've started working with the rapidshare.com API. I'm just wondering what is the best way to read the reply from and API call.
To be honest I think the API is all over the place. Some replies are comma delimited which is fine. I'm having with problems with the account info response. This is not comma delimited and the fields may not always be in the same order.
Here is a sample response:
accountid=123456 type=prem servertime=1260968445 addtime=1230841165 validuntil=1262377165 username=DOWNLOADER directstart=1 protectfiles=0 rsantihack=0 plustrafficmode=0 mirrors= jsconfig=1 email=take#hike.com lots=0 fpoints=12071 ppoints=10 curfiles=150 curspace=800426795 bodkb=5000000 premkbleft=23394289 ppointrate=93
I'm thinking that regex is the way to go here. Here is my expression that seems to cath all responses that contain values:
(accountid|type|servertime|addtime|validuntil|username|directstart|protectfiles|rsantihack|plustrafficmode|mirrors|jsconfig|email|lots|fpoints|ppoints|curfiles|curspace|bodkb|premkbleft|ppointrate|refstring|cookie)\=[\w._#]+
If the order of data is to be considered random then how do I determine which value is which?
I'm just curious as to how everybody else is working with this.
Thanks,
Conor
i assume c#.
string[] s = #"accountid=123456 type=prem servertime=1260968445 addtime=1230841165 validuntil=1262377165 username=DOWNLOADER directstart=1 protectfiles=0 rsantihack=0 plustrafficmode=0 mirrors= jsconfig=1 email=take#hike.com lots=0 fpoints=12071 ppoints=10 curfiles=150 curspace=800426795 bodkb=5000000 premkbleft=23394289 ppointrate=93".Split(" ");
var params = new Dictionary<string, string>();
foreach(var l in s)
{
var tmp = l.Split("=");
params[tmp[0]] = params[tmp[1]];
}
(it may contain bugs.. but the idea is obvious?)
You probably want to split this up into a Dictionary object of some kind, so that you can access the value by a key.
Here's an example of a C# console application that works with .NET 3.5:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace SO
{
class Program
{
static void Main(string[] args)
{
string input = #"accountid=123456 type=prem servertime=1260968445";
string pattern = #"(?<Key>[^ =]+)(?:\=)(?<Value>[^ ]+)(?=\ ?)";
Dictionary<string, string> fields =
(from Match m in Regex.Matches(input, pattern)
select new
{
key = m.Groups["Key"].Value,
value = m.Groups["Value"].Value
}
).ToDictionary(p => p.key, p => p.value);
//iterate over all fields
foreach (KeyValuePair<string, string> field in fields)
{
Console.WriteLine(
string.Format("{0} : {1}", field.Key, field.Value)
);
}
//get value from a key
Console.WriteLine(
string.Format("{0} : {1}", "type", fields["type"])
);
}
}
}
Link to another example in PHP:
How to use rapidshare API to get Account Details ?? PHP question
Here is what I have done.
It's basically just a working version the code from Yossarian.
// Command to send to API
String command = "sub=getaccountdetails_v1&type=prem&login="+Globals.username+"&password="+Globals.password;
// This will return the response from rapidshare API request.
// It just performs # webrequest and returs the raw text/html. It's only a few lines. Sorry I haven't included it here.
String input = executeRequest(command);
input = input.Trim();
string[] s = input.Split('\n');
Dictionary<string,string> terms = new Dictionary<string, string>();
foreach(var l in s)
{
String[] tmp = l.Split('=');
terms.Add(tmp[0], tmp[1]);
}
foreach (KeyValuePair<String, String> term in terms)
{
txtOutput.Text += term.Key + " :: " + term.Value+"\n";
}
Thanks for your help guys.