Regular expression (extract key/value pairs) - regex

I'm trying to extract a list (match) of key/value pairs from a string. Ex :
PATH_1:"/", PATH_2:"/OtherPath", TODAY:"2016-06-27",XYZ :"1234"
This should give :
Key Value
PATH_1 /
PATH_2 /OtherPath
TODAY 2016-06-27
XYZ 1234
Here is what I have so far as regex :
((?:"[^"]*"|[^:,])*):((?:"[^"]*"|[^:,])*)
This is well working except that when I'm adding a path having a '\'. Ex :
PATH_1:"c:\", PATH_2:"c:\OtherPath", TODAY:"2016-06-27"
I don't know how to instruct to regex expression to jump over semi-colon when found inside double quote sequence. Hope someone can help me.
PS : I'm using QT.
Best regards,

https://regex101.com/r/vB1rS1/2
It seems that just removing the : from the last [] may do it if the quotes are being removed.
((?:"[^"]*"|[^:,])*):((?:"[^"]*"|[^,])*)

Related

regular expression search backwards, How to deal with words with and without?

I tested by https://regexr.com/
There two sample words.
BOND_aa_SB1_66-1.pdf
BOND_bb_SB2.pdf
I want to extract SB1, SB2 from each sample.
but my regular expression is not perfect.
It is working
(?<=BOND_.*_).*
But It is difficult to write the following.
I try
(?<=BOND_.*_).*(?=(_|\.))
But first sample result is 'SB1_66-1'
I just want to extract SB1
sb1 The following may or may not exist. if there is content, it can be separated by starting with _.
How should I fix it?
To extract the third underscore-separated term, we can use re.search as follows:
inp = ["BOND_aa_SB1_66-1.pdf", "BOND_bb_SB2.pdf"]
output = [re.search(r'^BOND_[^_]+_([^_.]+)', x).group(1) for x in inp]
print(output) # ['SB1', 'SB2']
s = "BOND_aa_SB1_66-1.pdf BOND_bb_SB2.pdf"
(re.findall(r'(SB\d+)', s))
['SB1', 'SB2']

Wrong regexp query for elasticsearch

I have some problems with the regexp query for elasticsearch. In my index there's a text field with comma-separated numeric values (IDs), f.e.
2,140,3,2495
And I have the following query term:
"regexp" : {
"myIds" : {
"value" : "^2495,|,2495,|,2495$|^2495$",
"boost" : 1
}
}
But my result list is empty.
Let me say that I know that regexp queries are kind of slow but the index still exists and is filled with millions of documents so unfortunately it's not an option to restructure it. So I need a regex solution.
In ElasticSearch regex, patterns are anchored by default, the ^ and $ are treated as literal chars.
What you mean to use is "2495,.*|.*,2495,.*|.*,2495|2495" - 2495, at the start of string, ,2495, in the middle, ,2495 at the end or a whole string equal to 2495.
Or, you may use a simpler
"(.*,)?2495(,.*)?"
That means
(.*,)? - an optional text (not including line breaks) ending with ,
2495 - your value
(,.*)? - an optional text (not including line breaks) ending with ,
Here is an online demo showing how this expression works (not a proof though).
Ok, I got it to work but run in another problem now. I built the string as follows:
(.*,)?2495(,.*)?|(.*,)?10(,.*)?|(.*,)?898(,.*)?
It works good for a few IDs but if I have let's say 50 IDs, then ES throws an exception which says that the regexp is too complex to process.
Is there a way to simplify the regexp or restructure the query it selves?

Regex to replace all occurences of a character within a given context

I am trying to write a search and replace regex (in ruby) to replace all instances of a character in a string in a given context.
The regex needs to replace all instances of "." in a json key, and I'm battling with references. I have a feeling that I need to use a lookaround in some way, but the variations I've tried I can't seem to get working.
Some example strings:
, "key1.name" : " value.something "
, "key2.complex.name" : "value.else"
, "this.is.the.most.complex.name" : "value"
I initially had this regex to replace a single occurrence (replacing it with "FULLSTOP"):
s/, "([^.]+)\.([^"]+)" :/, "\1FULLSTOP\2" :/gā€ā€
Desired output:
, "key1FULLSTOPname" : " value.something "
, "key2FULLSTOPcomplexFULLSTOPname" : "value.else"
, "thisFULLSTOPisFULLSTOPtheFULLSTOPmostFULLSTOPcomplexFULLSTOPname" : "value"
I'm guessing I need to use a (?=\.) somehow in the search, but not sure how to use this correctly with references. I am using the opening , and ending : as a way of defining the context for a json key.
thanks in advance.
(?=.*?\:)\.
Use this.See demo.
http://regex101.com/r/cH8vN2/5
Edit:
(?=.*?\"\s*\:)\.
Use this to be very sure.
See demo.
http://regex101.com/r/cH8vN2/6
You can use the following as a sample :
str = ', "this.is.the.most.complex.name" : "value';
str = str.gsub(/\.+/, 'FULLSTOP');
puts str;
I have not taken care of the 'value' part.
You should be able to do that easily.

Perl: Help writing a regular expression

I am trying to write a common regular expression for the below 3 cases:
Supernatural_S07E23_720p_HDTV_X264-DIMENSION.mkv
the.listener.313.480p.hdtv.x264-2hd.mkv
How.I.met.your.mother.s02e07.hdtv.x264-xor.avi
Now my regular exoression should remove the series name from the original string i,e the output of above string will be:
S07E23_720p_HDTV_X264-DIMENSION.mkv
313.480p.hdtv.x264-2hd.mkv
s02e07.hdtv.x264-xor.avi
Now for the basic case of supernatural string I wrote the below regex and it worked fine but as soon as the series name got multiple words it fails.
$string =~ s/^(.*?)[\.\_\- ]//i; #delimiter can be (. - _ )
So, I have no idea how to proceed for the aboves cases I was thinking along the lines of \w+{1,6} but it also failed to do the required.
PS: Explanation of what the regular expression is doing will be appreciated.
you can detect if the .'s next token contains digit, if not, consider it as part of the name.
HOWEVER, I personally think there is no perfect solution for this. it'd still meet problem for something like:
24.313.480p.hdtv.x264-2hd.mkv // 24
Warehouse.13.s02e07.hdtv.x264-xor.avi // warehouse 13
As StanleyZ said, you'll always get into trouble with names containing numbers.
But, if you take these special cases appart, you can try :
#perl
$\=$/;
map {
if (/^([\w\.]+)[\.\_]([SE\d]+[\.\_].*)$/i) {
print "Match : Name='$1' Suffix='$2'";
} else {
print "Did not match $_";
}
}
qw!
Supernatural_S07E23_720p_HDTV_X264-DIMENSION.mkv
the.listener.313.480p.hdtv.x264-2hd.mkv
How.I.met.your.mother.s02e07.hdtv.x264-xor.avi
!;
which outputs :
Match : Name='Supernatural' Suffix='S07E23_720p_HDTV_X264-DIMENSION.mkv'
Match : Name='the.listener' Suffix='313.480p.hdtv.x264-2hd.mkv'
Match : Name='How.I.met.your.mother' Suffix='s02e07.hdtv.x264-xor.avi'
note : aren't you doing something illegal ? ;)

Regex to replace string with another string in MS Word?

Can anyone help me with a regex to turn:
filename_author
to
author_filename
I am using MS Word 2003 and am trying to do this with Word's Find-and-Replace. I've tried the use wildcards feature but haven't had any luck.
Am I only going to be able to do it programmatically?
Here is the regex:
([^_]*)_(.*)
And here is a C# example:
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
String test = "filename_author";
String result = Regex.Replace(test, #"([^_]*)_(.*)", "$2_$1");
}
}
Here is a Python example:
from re import sub
test = "filename_author";
result = sub('([^_]*)_(.*)', r'\2_\1', test)
Edit: In order to do this in Microsoft Word using wildcards use this as a search string:
(<*>)_(<*>)
and replace with this:
\2_\1
Also, please see Add power to Word searches with regular expressions for an explanation of the syntax I have used above:
The asterisk (*) returns all the text in the word.
The less than and greater than symbols (< >) mark the start and end
of each word, respectively. They
ensure that the search returns a
single word.
The parentheses and the space between them divide the words into
distinct groups: (first word) (second
word). The parentheses also indicate
the order in which you want search to
evaluate each expression.
Here you go:
s/^([a-zA-Z]+)_([a-zA-Z]+)$/\2_\1/
Depending on the context, that might be a little greedy.
Search pattern:
([^_]+)_(.+)
Replacement pattern:
$2_$1
In .NET you could use ([^_]+)_([^_]+) as the regex and then $2_$1 as the substitution pattern, for this very specific type of case. If you need more than 2 parts it gets a lot more complicated.
Since you're in MS Word, you might try a non-programming approach. Highlight all of the text, select Table -> Convert -> Text to Table. Set the number of columns at 2. Choose Separate Text At, select the Other radio, and enter an _. That will give you a table. Switch the two columns. Then convert the table back to text using the _ again.
Or you could copy the whole thing to Excel, construct a formula to split and rejoin the text and then copy and paste that back to Word. Either would work.
In C# you could also do something like this.
string[] parts = "filename_author".Split('_');
return parts[1] + "_" + parts[0];
You asked about regex of course, but this might be a good alternative.