Ruby Regexp match matching repetitive values - ruby

I'm facing some issues with Ruby Regexp match.
I have the following query and I'd like to scan my parameters:
EXEC sp_executesql N'exec dbo.MyProcedure #UserID=#p0,#Products=#p1,#CountryCodes=#p2'
, N'#p0 int,#p1 nvarchar(max) ,#p2 nvarchar(max)'
, #p0 = 123569
, #p1 = N'1633,1634'
, #p2 = N'39A,CS,DE,ES,FR,GB,IT,NL,AB,BS,BU,CR,ET,FI,HU,LA,LT,MD,ME,MV,PL,RO,RS,SK,SV,GR,PT,TR,AT,CH,LI,GG,KS,UK,GI,MN,RR,CY,MT,BL,RU,DK,NO,SE,BE,IC,IE,LX'
I've just formatted query to look neat and readable. In my source there are fewer tabs and whitespaces.
Ideally, I'd like to get three matches:
#p0 = 123569
#p1 = N'1633,1634'
#p2 = N'39A,CS,DE,ES,FR,GB,IT,NL,AB,BS,BU,CR,ET,FI,HU,LA,LT,MD,ME,MV,PL,RO,RS,SK,SV,GR,PT,TR,AT,CH,LI,GG,KS,UK,GI,MN,RR,CY,MT,BL,RU,DK,NO,SE,BE,IC,IE,LX'
However, my Regexp pattern merges #p1 and #p2 and this is what I get:
#p0 = 123569
#p1 = N'1633,1634',#p2 = N'39A,CS,DE,ES,FR,GB,IT,NL,AB,BS,BU,CR,ET,FI,HU,LA,LT,MD,ME,MV,PL,RO,RS,SK,SV,GR,PT,TR,AT,CH,LI,GG,KS,UK,GI,MN,RR,CY,MT,BL,RU,DK,NO,SE,BE,IC,IE,LX'
I can see where's the issue, however I'm quite new to Regexp and I cannot figure out how to write it properly. This is my expression:
(\#p[0-9]+)+\=(\N\'.*\'|[0-9]+|NULL)
I'm testing my Regex expression here: http://rubular.com/r/OF5EVD5Nau

You main problem is the .* part in the second alternation, by default regex are greedy and match as much as possible.
You can turn it into lazy or ungreedy by adding a ? after the repetition operator.
So with little change this would do:
(#p[0-9]+)\s+=\s+(\d+|N'.+?'$|NULL)
Rubular example
There's some unknown from you description on the spaces, I used + as repetition operator assuming there will be at least 1 present around the = sign, as in the single quotes, I assume they are never empty. Replace by * if they are optionnal.

Related

Difference in a one line block code between === and match?

I have the following code example to check whether some elements in an array match or not the given regular expression:
["SELECT column1, column2 FROM table1, table2 WHERE column2='value';",
"SELECT * FROM Customers WHERE Last_Name='Smith';",
"SELECT * FROM Friends"].none? { |sql| /WHERE/i.match?(sql) }
# false
As you can see, I'm using match? just to see if both the receiver and the method parameter match. I'm not interested on the pros of using match as it's stated on the docs:
Returns a true or false indicates whether the regexp is matched or not without updating $~ and other related variables. If the second parameter is present, it specifies the position in the string to begin the search.
So, I could easily use === for that:
["SELECT column1, column2 FROM table1, table2 WHERE column2='value';",
"SELECT * FROM Customers WHERE Last_Name='Smith';",
"SELECT * FROM Friends"].none? { |sql| /WHERE/ === sql }
# false
Which returns the very same. Maybe isn't so common to use case equality for this kind of things, but that allows me to pass the regular expression as the none? parameter, and avoid opening the block, as I'm using Ruby 2.5+:
array.none?(/WHERE/) # false
And works pretty much the same (also the same for every enumerable predicate method):
array.any? { |sql| /WHERE/i.match?(sql) } # true
array.any? { |sql| /WHERE/ === sql } # true
array.any?(/WHERE/) # true
So, my question is; would it be the same for me, considering these cases to use === to check every string instance in the arrays match with the given regular expression? If so, I could replace them all to just pass the regular expression as the method (none?, any?) parameter.
The reason for Regexp#=== existing is primarily for use in case statements, like:
case (str)
when /WHERE/i
# ...
end
As internally that calls the === to check for matches. This is why you can do a lot of really wild things like:
case (str)
when String
when 0..20
when 'example'
when /text/
end
Among other things, all by virtue of the === comparison.
It's worth noting it's not intended to be used as you have. match? communicates quite clearly your intent, but === may be confusing as it looks a lot like == which indicates "comparison", but this is not any ordinary comparison.
The good news is Ruby allows using a regular expression directly with any? as well as an alternative like:
[
"SELECT column1, column2 FROM table1, table2 WHERE column2='value';",
"SELECT * FROM Customers WHERE Last_Name='Smith';",
"SELECT * FROM Friends"
].grep(/WHERE/i).any?
Where the grep method can take either a string or a regular expression.
The grep method is great for filtering, but if you just want to know if any of them match it's not as efficient as any?, so I'd use that instead.

Oracle Pattern matching

In Oracle I want to check whether the string has "=' sign at the end. could you please let me know how to check it. If it has '=' sign at the end of string, I need to trailing that '=' sign.
for eg,
varStr VARCHAR2(20);
varStr = 'abcdef='; --needs to trailing '=' sign
I don't think you need "pattern matching" here. Just check if the last character is the =
where substr(varstr, -1, 1) = '='
substr when called with a negative position will work from the end of the string, so substr(varstr,-1,1) extracts the last character of the given string.
Use the REGEX_EXP function. I'm putting a sql command since you didn't specify on your question.:
select *
from someTable
where regexp_like( someField, '=$' );
The pattern $ means that the precedent character should be at the end of the string.
see it here on sql fiddle: http://sqlfiddle.com/#!4/d8afd/3
It seems that substr is the way to go, at lease with my sample data of about 400K address lines this returns 1043 entries that end in 'r' in an average of 0.2 seconds.
select count(*) from addrline where substr(text, -1, 1) = 'r';
On the other hand, the following returns the same results but takes 1.1 seconds.
select count(*) from addrline where regexp_like(text, 'r$' );

Oracle regex for all characters after a specific character

I need to get all characters after the last 'R' from a part number like this:
223A GHH R337716
So far I've got:
REGEXP_SUBSTR(CUST_PART_NO,'R(.*)')
This returns R337716, but I don't want the 'R' and I'm not sure if it would work if there was more than one 'R' in the string.
Then you have to replace the string with groups of expressions like this:
regexp_replace( CUST_PART_NO, '(.*)(R)(.*)', '\3' )
See it here on sqlfiddle: http://sqlfiddle.com/#!4/3ec77/2
What I'm saying with this expression is:
get everything until R make it as a group 1 expression the first (.*)
get the R make it the second group (R)
get everything else and make it the third group (.*)
The parenthesis on a regular expression define groups of expressions.
What about
ltrim(REGEXP_SUBSTR(CUST_PART_NO,'R(.*)'), 'R')

ruby regex not working to remove class name from sql

I have:
BEFORE Gsub sql ::::
SELECT record_type.* FROM record_type WHERE (name = 'Registrars')
sql = sql.gsub(/SELECT\s+[^\(][A-Z]+\./mi,"SELECT ")
AFTER GSUB SQL ::::
SELECT record_type.* FROM record_type WHERE (name = 'Registrars')
The desired result is to remove the "record_type." from the statement:
So it should be :
SELECT * FROM record_type WHERE (name = 'Registrars')
After the regex is run.
I didn't write this, it's in the asf-soap-adaptor gem. Can someone tell me why it doesn't work, and how to fix?
I suppose it should be written like this...
sql = sql.gsub(/SELECT\s+[^\(][A-Z_]+\./mi,"SELECT ")
... as the code in the question won't match if the field name contains _ (underscore) symbol. I suppose that's why this code is in gem: it can work in some conditions (i.e., with underscoreless field names).
Still, I admit I don't understand why exactly this replacement should be done - and shouldn't it include 0-9 check as well (as, for example, 'record_id1' field still won't be matched - and replaced - by the character class in the regular expression; you may have to either expand it, like [0-9A-Z_], or just replace completely with \w).
so your before and after gsubs are the same? I can't tell you why it doesn't work if you dont tell me your expected result. Also for help with interpreting ruby regular expressions check out rubular.com

Whats the XPath equivalent to SQL In query?

I would like to know whats the XPath equivalent to SQL In query. Basically in sql i can do this:
select * from tbl1 where Id in (1,2,3,4)
so i want something similar in XPath/Xsl:
i.e.
//*[#id= IN('51417','1121','111')]
Please advice
(In XPath 2,) the = operator always works like in.
I.e. you can use
//*[#id = ('51417','1121','111')]
A solution is to write out the options as separate conditions:
//*[(#id = '51417') or (#id = '1121') or (#id = '111')]
Another, slightly less verbose solution that looks a bit like a hack, though, would be to use the contains function:
//*[contains('-51417-1121-111-', concat('-', #id, '-'))]
Literally, this means you're checking whether the value of the id attribute (preceeded and succeeded by a delimiter character) is a substring of -51417-1121-111-. Note that I am using a hyphen (-) as a delimiter of the allowable values; you can replace that with any character that will not appear in the id attribute.

Resources