my application is going to need a string matching function between an inputed string and a string stored in my DB. Those strings concerns product dimensions (like length, heigh etc.) My goal is to check if the string inputed already exists in my database but maybe with another pattern , for example :
input : "vis 4*40" should return true if I have something like "vis 4X40" or "vis 4 x 40" or "vis 4* 40" in my database.
The only way i've found yet is to normalize my databse using a regexp to replace pattern like :
\d+ *[xX*] *\d+
with a normalized one (for example NumberXNumber), do the same with the string in input then try to find it. However I was wondering if any tool already existed and would allow me to do that. (I'm working in C# .NET V4)
A better way would be to concatenate both the data and then match them
string target=inputString+"#"+storedString;
if(Regex.IsMatch(target,"(\d+) *[xX*] *(\d+)#\1 *([xX*]) *\2"))
//the string is in the database
else
//it is not
Just use the user-provided wildcard, replace the * with % and query your table: SELECT col FROM table WHERE col LIKE 'vis 4%40'
Please make sure you execute your queries with parameters.
Related
I have a string as shown below
string names = "<?startname; Max?><?startname; Alex?><?startname; Rudy?>";
is there any way I can split this string and add Max , Alex and Rudy into a separate list ?
Sure, split on two strings (all that consistently comes before, and all that consistently comes after) and specify that you want Split to remove the empties:
var r = names.Split(new[]{ "<?startname; ", "?>" }, StringSplitOptions.RemoveEmptyEntries);
If you take out the RemoveEmptyEntries it will give you a more clear idea of how the splitting is working, but in essence without it you'd get your names interspersed with array entries that are empty strings because split found a delimiter (the <?...) immediately following another (the ?>) with an empty string between the delimiters
You can read the volumes of info about this form of split here - that's a direct link to netcore3.1, you can change your version in the table of contents - this variant of Split has been available since framework2.0
You did also say "add to a separate list" - didn't see any code for that so I guess you will either be happy to proceed with r here being "a separate list" (an array actually, but probably adequately equivalent and easy to convert with LINQ's ToList() if not) or if you have another list of names (that really is a List<string>) then you can thatList.AddRange(r) it
Another Idea is to use Regex
The following regex should work :
(?<=; )(.*?)(?=\s*\?>)
I am generating SQL code for different types of databases. To do that dynamically, certain parameters of the SQL script are stored in variables.
One such stored parameter is the comparison expression for certain queries.
Lets say I have a Dogs table with a Name, DateOfBirth and Gender columns, then I have comparison expressions in a variable such as:
string myExpression = "Gender=1";
string myExpression2 = "Gender=1 AND Name='Bucky'";
I would build the following SQL string then:
string mySqlString = "SELECT * FROM "dbo"."Dogs" WHERE " + myExpression;
The problem is, that for Oracle syntax, I have to quote the column names (as seen at dbo.Dogs above). So I need to create a string from the stored expression which looks like:
string quotedExpression = "\"Gender\"=1";
Is there a fast way, to do this? I was thinking of splitting the string at the comparison symbol, but then I would cut the symbol itself, and it wouldn't work on complex conditions either. I could iterate through the whole string, but that would include lot of conditions to check (the comparison symbol can be more than one character (<>) or a keyword (ANY,ALL,etc.)), and I rather avoid lots of loops.
IMO the problem here is the attempt to use myExpression / myExpression2 as naked SQL strings. In addition to being a massive SQL-injection hole, it causes problems like you're seeing now. When I need to do this, I treat the filter expression as a DSL, which I then parse into an AST (using something like a modified shunting yard algorithm - although there are other ways to do it). So I end up with
AND
=
Gender
1
=
Name
'Bucky'
Now I can walk that tree (visitor pattern), looking at each. 1 looks like an integer (int.TryParse etc), so we can add a parameter with that value. 'Bucky' looks like a string literal (via the quotes), so we can add a string-based parameter with the value Bucky (no quotes in the actual value). The other two are non-quoted strings, so they are column names. We check them against our model (white-list), and apply any necessary SQL syntax such as escaping - and perhaps aliasing (it might be Name in the DSL, but XX_Name2_ChangeMe in the database). If the column isn't found in the model: reject it. If you can't understand an expression completely: reject it.
Yes, this is more complex, but it will keep you safe and sane.
There may be libraries that can already do the expression parsing (to AST) for you.
In our C# desktop-application we generate a lot of dynamic sql-queries. Now we have some troubles with single quotes in strings. Here's a sample:
INSERT INTO Addresses (CompanyName) VALUES ('Thomas' Imbiss')
My question is: How can I find and replace all single quotes between 2 other single quotes in a string? Unfortunately I can't replace the single quotes when creating the different queries. I can only do that after the full query is created and right before the query gets executed.
I tried this pattern (Regular Expressions): "\w\'\w"
But this pattern doesn't work, because after "s'" there's a space instead of a char.
I am sorry to say, there is no solution in approach you expect.
For example, have these columns and values:
column A, value ,A',
column B, value ,B',
If they are together in column list, you have ',A',',',B','.
Now, where is the boundary between first and second value? It is ambiguous.
You must take action when creating text fields for SQL. Either use SQL parameters or properly escape qoutes and other problematic characters there.
Consider showing the above ambiguous example to managers, pushing the whole problem back as algorithmically unsolvable at your end. Or offer implementing a guess-work and ask them whether they will be happy if content of several text fields can get mixed in some cases like above one.
At time of SQL query creation, if they do not want to start using SQL parameters, the solution for enquoting any input string is as simple as replacing:
string Enquote(string input)
{
return input.All(c => Strings.AscW(c) < 128) ? "'" : "N'"
+ input.Replace("'", "''")
+ "'"
}
Of course, it can have problem with deliberately malformed Unicode strings (surrogate pairs to hide ') but it is not normally possible to produce these strings through the user interface. Generally this can be still faster than converting all queries to versions with SQL parameters.
Is it possible to generate regular expressions from a user entered string? Are there any C# libraries to do this?
For example a user enters a string e.g. ABCxyz123 and the C# code automatically generates [A-Z]{3}[a-z]{3}\d{3}.
This is a simple string but we could have more complicated strings like
MON-0123/AB/5678-abc 2/7
Or
1234-678/abc::1234ABC?246
I already have a string tokeniser (from a previous stackoverflow question) so I could construct a regex from the list of tokens.
But I was wondering if there is a lib or C# code out there that’ll do it.
Edit: Important, I should of also said: It's not the actual character in the string that are important but the type of character and how many.
e.g A user could enter a "pattern" string of ABCxyz123.
This would be interpreted as
3 upper case alphas followed by
3 lower case alphas followed by
3 digits
So other users (when complied) must enter strings that match that pattern [A-Z]{3}[a-z]{3}\d{3}., e.g. QAZplm789
It's the format of user entered strings that's need to be checked not the actual content if that makes sense
Jerry has a related link
creating a regular expression for a list of strings
There are a few other links off this.
I'm not trying to do anything complicated e.g NLP etc.
I could use C# expression builder and dynamic linq at a push, but that seems overkill and a code maintainable nightmare .
I'll write my own "simple" regex builder from the tokenized string.
Example Use Case:
An admin office user where I work could setup the string patterns for each field by typing a string pattern, My code converts this to a regex, I store these in a database.
E.g: Field one requires 3 digits at the start. If there are 2 digits then send to workflow 1 if 3 then send to workflow 2. I could simply check the number of chars by substr or what ever. But this would be a concrete solution.
I am trying to do this generically for multiple documents with multiple fields. Also, each field could have multiple format checkers.
I don't want to write specific C# checks for every single field in numerous documents.
I'll get on with it, should keep me amused for a couple of days.
I'm looking at UK postcodes and trying to work out how I can take data from a database (the first part of a UK postcode) and dynamically create a regexp for them using c#. For example:
AB44-56
I know what I want as an output:
AB([4][4-9]|[5][0-6])+
However, I can't work out how I might be able to do this with logic, perhaps I need to split the Letters from the numbers first, but i can't do that using split.
I have other combinations too - single range:
AB31 would be AB[3][1]+
Some with just letters:
BT would be BT+
Some with a single letter and 1 or two numbers:
G83 Would be G[8][3]
Any suggestions or guidance would be very much appriciated how this may be coded.
afrom wikipedia UK postal codes :
This can be generalised as: (one or two letters)(number between 0 and
99)(zero or one letter)(space)(single digit)(two letters)
so
^[A-Z,a-z]{0,2}\d+[A-Z,a-z]?\s\d[A-Z,a-z]{2}$
might work.
EDIT: Also if you are trying to restric the postal codes to say those with the same prefix as the ones in the database you could do this.
var source = "BTasdfweasdf"; //from the database
var input = "BT1A 1BB"; //from the somewhere else
var regex = Regex.Replace(source, #"(^[A-z,a-z]{0,2})(.*)", #"$1\d+[A-Z,a-z]?\s\d[A-Z,a-z]{2}$");
var match = Regex.Match(input,regex);