preg_match optional elements in string - string

I have two strings which contain up to 3 elements:
1) anychar[price]{alphanum} e.g. a1\')[=00.00]{a1234}
2) anychar:anychar{alphanum} e.g. a1\'):a2\'){a1234}
...but the {} element is optional and may not always be there. I wrote the following patterns (respectively):
1) /(.+)\[(.+)\]\{*(\w+)*\}*/ - works as expected
2) /(.+)\:(.+)\{*(\w+)*\}*/ - works fine if the {} element is removed, but not with it.
The result array for 2 is as follows:
(
[0] => a1\'):a2\'){a123}
[1] => a1\')
[2] => a2\'){a123}
)
I've tried a few different permutations of the above but no dice. Any ideas?

First you should remove the * after {, } and (\w+).
'/(.+)\:(.+)\{(\w+)\}/'
Gives
array(4) {
[0]=>
string(18) "a1\'):a2\'){a1234}"
[1]=>
string(5) "a1\')"
[2]=>
string(5) "a2\')"
[3]=>
string(5) "a1234"
}
* means either 0, 1 or several, and PCRE tries to find the quickest route it can, so if you make the whole third part optional (by using * everywhere) then the quickest route is to have everything included in the second group and skip the third, that's why your code didn't work.
Now in order to deal with the fact that the third part is optional, you have to use a positive lookahead: in the second group, you will ask pcre to select it only if it can matches another regex after it. The final regex is this:
'/(.+)\:(.+(?=(?:(?<=[^}])$|\{(\w+)\})))/'
What I changed is that:
inside the second group, i added a positive lookahead in the form (?=regex). As said, this means it has to match. Lookahead are not selective by default, which means that they don't create a entry in your final result/they are not returned to you.
inside that lookahead, I created two cases, which means that in order to match, the .+ from the second group will have to match either case of my lookahead.
The first case is very basic, it means end of string not preceded by a }, this will match the string when the 3rd part is not there
the second case if you selector for the 3rd group, we make it selectable so that it will be returned in the results if present

Related

Formatting string in Powershell but only first or specific occurrence of replacement token

I have a regular expression that I use several times in a script, where a single word gets changed but the rest of the expression remains the same. Normally I handle this by just creating a regular expression string with a format like the following example:
# Simple regex looking for exact string match
$regexTemplate = '^{0}$'
# Later on...
$someString = 'hello'
$someString -match ( $regexTemplate -f 'hello' ) # ==> True
However, I've written a more complex expression where I need to insert a variable into the expression template and... well regex syntax and string formatting syntax begin to clash:
$regexTemplate = '(?<=^\w{2}-){0}(?=-\d$)'
$awsRegion = 'us-east-1'
$subRegion = 'east'
$awsRegion -match ( $regexTemplate -f $subRegion ) # ==> Error
Which results in the following error:
InvalidOperation: Error formatting a string: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
I know what the issue is, it's seeing one of my expression quantifiers as a replacement token. Rather than opt for a string-interpolation approach or replace {0} myself, is there a way I can tell PowerShell/.NET to only replace the 0-indexed token? Or is there another way to achieve the desired output using format strings?
If a string template includes { and/or } characters, you need to double these so they do not interfere with the numbered placeholders.
Try
$regexTemplate = '(?<=^\w{{2}}-){0}(?=-\d$)'

Python regex search until specific word and exclude everything behind it

I have a script that always have the "get the" and the "get" in a string.
The "ONE TWO THREE" can vary, like it also can be "THIRTEEN FORTY" or "SIX". After these variations there will always be a 2nd "get".
I have the following code:
variable = 'get the ONE TWO THREE get FOUR FIVE'
myVariable = re.compile(r'(?<=get the) .*')
myVariableSearch = myVariable.search(variable)
mySearchGroup = myVariableSearch.group()
print(mySearchGroup)
#prints ONE TWO THREE get FOUR FIVE
I want my script to exclude the 2nd "get" and everything behind it. My desired result is to be just the "ONE TWO THREE".
How do I exclude this? Any help would be appreciated!
You can use
\bget\s+the\s+(.*?)(?=\s*\bget\b|$)
See the regex demo.
Details
\bget\s+the\s+ - whole word get, 1+ whitespaces, the, 1+ whitespaces
(.*?) - Group 1:
(?=\s*\bget\b|$) - a positive lookahead that requires 0+ whitespaces and then a whole word get, or end of string immediately on the right of the current location.
See the Python demo:
import re
variable = 'get the ONE TWO THREE get FOUR FIVE'
myVariableSearch = re.search(r'\bget\s+the\s+(.*?)(?=\s*\bget\b|$)', variable)
mySearchGroup = ''
if myVariableSearch:
mySearchGroup = myVariableSearch.group(1)
print(mySearchGroup)
# => ONE TWO THREE

Node.JS - if a string includes some strings with any characters in between

I am testing a string that contains an identifier for which type of device submitted the string. The device type identifier will be something like "123456**FF789000AB" where the * denote any character could be used at this position. I run a series of functions to parse additional data and set variables based on the type of device submitting the data. Currently, I have the following statement:
if (payload[4].includes("02010612FF590080BC")) { function(topic, payload, intpl)};
The string tested in the includes() test will always start with 020106, but the next two characters could be anything. Is there a quick regex I could throw in the includes function, or should I organize the test in a different way?
To match the "020106**FF590080BC" pattern, where * can be anything, you can use RegExp.test() and the regular expression /020106..FF590080BC/:
if (/020106..FF590080BC/.test(payload[4])) { ... }
Also, if you require that the pattern must match the beginning of the string:
if (/^020106..FF590080BC/.test(payload[4])) { ... }

Display the specific part of the string in PostgreSQL 9.3

I have a string to modify as per the requirements.
For example:
The given string is:
str1 varchar = '123,456,789';
I want to show the string as:
'456,789'
Note: The first part (delimited) with comma, I want to remove from string and show the rest of string.
In SQL Server I used STUFF() function.
SELECT STUFF('123,456,789',1,4,'');
Result:
456,789
Question: Is there any string function in PostgreSQL 9.3 version to do the same job?
you can use regular expressions:
select substring('123,456,789' from ',(.*)$');
The comma matches the first comma found in the string. The part inside the brackets (.*) is returned from the function. The symbol $ means the end of the string.
A alternative solution without regular expressions:
select str, substring(str from position(',' in str)+1 for length(str)) from
(select '123,456,789'::text as str) as foo;
You could first turn the string to array and return second and third cell:
select array_to_string((regexp_split_to_array('123,456,789', ','))[2:3], ',')
Or you could use substring-function with regular expressions (pattern matching):
SELECT substring('123,456,789' from '[0-9]+,([0-9]+,[0-9]+)')
[0-9]+ means one or more digits
parentheses tell to return that part from the string
Both solutions work on your specific string.
Your The SQL Server example indicates you just want to remove the first 4 characters, which makes the rest of your question seem misleading because it completely ignores what's in the string. Only the positions matters.
Be that as it may, the simple and cheap way to cut off leading characters is with right():
SELECT right('123,456,789', -4);
SQL Fiddle.

Lua: Search a specific string

Hi all tried all the string pattrens and library arguments but still stuck.
i want to get the name of the director from the following string i have tried the string.matcH but it matches the from the first character it finD from the string
the string is...
fixstrdirector = {id:39254,cast:[{id:15250,name:Hope Davis,character:Aunt Debra,order:5,cast_id:10,profile_path:/aIHF11Ss8P0A8JUfiWf8OHPVhOs.jpg},{id:53650,name:Anthony Mackie,character:Finn,order:3,cast_id:11,profile_path:/5VGGJ0Co8SC94iiedWb2o3C36T.jpg},{id:19034,name:Evangeline Lilly,character:Bailey Tallet,order:2,cast_id:12,profile_path:/oAOpJKgKEdW49jXrjvUcPcEQJb3.jpg},{id:6968,name:Hugh Jackman,character:Charlie Kenton,order:0,cast_id:13,profile_path:/wnl7esRbP3paALKn4bCr0k8qaFu.jpg},{id:79072,name:Kevin Durand,character:Ricky,order:4,cast_id:14,profile_path:/c95tTUjx5T0D0ROqTcINojpH6nB.jpg},{id:234479,name:Dakota Goyo,character:Max Kenton,order:1,cast_id:15,profile_path:/7PU6n4fhDuFwuwcYVyRNVEZE7ct.jpg},{id:8986,name:James Rebhorn,character:Marvin,order:6,cast_id:16,profile_path:/ezETMv0YM0Rg6YhKpu4vHuIY37D.jpg},{id:930729,name:Marco Ruggeri,character:Cliff,order:7,cast_id:17,profile_path:/1Ox63ukTd2yfOf1LVJOMXwmeQjO.jpg},{id:19860,name:Karl Yune,character:Tak Mashido,order:8,cast_id:18,profile_path:/qK315vPObCNdywdRN66971FtFez.jpg},{id:111206,name:Olga Fonda,character:Farra Lemkova,order:9,cast_id:19,profile_path:/j1qabOHf3Pf82f1lFpUmdF5XvSp.jpg},{id:53176,name:John Gatins,character:Kingpin,order:10,cast_id:41,profile_path:/A2MqnSKVzOuBf8MVfNyve2h2LxJ.jpg},{id:1126350,name:Sophie Levy,character:Big Sister,order:11,cast_id:42,profile_path:null},{id:1126351,name:Tess Levy,character:Little Sister,order:12,cast_id:43,profile_path:null},{id:1126352,name:Charlie Levy,character:Littlest Sister,order:13,cast_id:44,profile_path:null},{id:187983,name:Gregory Sims,character:Bill Panner,order:14,cast_id:45,profile_path:null}],crew:[{id:58726,name:Leslie Bohem,department:Writing,job:Screenplay,profile_path:null},{id:53176,name:John Gatins,department:Writing,job:Screenplay,profile_path:/A2MqnSKVzOuBf8MVfNyve2h2LxJ.jpg},{id:17825,name:Shawn Levy,department:Directing,job:Director,profile_path:/7f2f8EXdlWsPYN0HPGcIlG21xU.jpg},{id:12415,name:Richard Matheson,department:Writing,job:Story,profile_path:null},{id:57113,name:Dan Gilroy,department:Writing,job:Story,profile_path:null},{id:25210,name:Jeremy Leven,department:Writing,job:Story,profile_path:null},{id:17825,name:Shawn Levy,department:Production,job:Producer,profile_path:/7f2f8EXdlWsPYN0HPGcIlG21xU.jpg},{id:34970,name:Susan Montford,department:Production,job:Producer,profile_path:/1XJt51Y9ciPhkHrAYE0j6Jsmgji.jpg},{id:3183,name:Don Murphy,department:Production,job:Producer,profile_path:null},{id:34967,name:Rick Benattar,department:Production,job:Producer,profile_path:null},{id:1126348,name:Eric Hedayat,department:Production,job:Producer,profile_path:null},{id:186721,name:Ron Ames,department:Production,job:Producer,profile_path:null},{id:10956,name:Josh McLaglen,department:Production,job:Executive Producer,profile_path:null},{id:57634,name:Mary McLaglen,department:Production,job:Executive Producer,profile_path:null},{id:23779,name:Jack Rapke,department:Production,job:Executive Producer,profile_path:null},{id:488,name:Steven Spielberg,department:Production,job:Executive Producer,profile_path:/cuIYdFbEe89PHpoiOS9tmo84ED2.jpg},{id:30,name:Steve Starkey,department:Production,job:Executive Producer,profile_path:null},{id:24,name:Robert Zemeckis,department:Production,job:Executive Producer,profile_path:/isCuZ9PWIOyXzdf3ihodXzjIumL.jpg},{id:531,name:Danny Elfman,department:Sound,job:Original Music Composer,profile_path:/pWacZpYPos8io22nEiim7d3wp2j.jpg},{id:18265,name:Mauro Fiore,department:Crew,job:Cinematography,profile_path:null},{id:54271,name:Dean Zimmerman,department:Editing,job:Editor,profile_path:null},{id:25365,name:Richard Hicks,department:Production,job:Casting,profile_path:null},{id:5490,name:David Rubin,department:Production,job:Casting,profile_path:null},{id:52088,name:Tom Meyer,department:Art,job:Production Design,profile_path:null}]}
i have tried string.match(fixstrdirector,"name:(.+),department:Directing")
but it gives me the from the first occurace it find the name to the end of thr string
output:
Hope Davis,character:Aunt Debra,order:5,cast_id:10,profile_path:/aIHF11Ss8P0A8JUfiWf8OHPVhOs.jpg},{id:53650,name:Anthony Mackie,character:Finn,order:3,cast_id:11,profile_path:/5VGGJ0Co8SC94iiedWb2o3C36T.jpg},{id:19034,name:Evangeline Lilly,character:Bailey Tallet,order:2,cast_id:12,profile_path:/oAOpJKgKEdW49jXrjvUcPcEQJb3.jpg},{id:6968,name:Hugh Jackman,character:Charlie Kenton,order:0,cast_id:13,profile_path:/wnl7esRbP3paALKn4bCr0k8qaFu.jpg},{id:79072,name:Kevin Durand,character:Ricky,order:4,cast_id:14,profile_path:/c95tTUjx5T0D0ROqTcINojpH6nB.jpg},{id:234479,name:Dakota Goyo,character:Max Kenton,order:1,cast_id:15,profile_path:/7PU6n4fhDuFwuwcYVyRNVEZE7ct.jpg},{id:8986,name:James Rebhorn,character:Marvin,order:6,cast_id:16,profile_path:/ezETMv0YM0Rg6YhKpu4vHuIY37D.jpg},{id:930729,name:Marco Ruggeri,character:Cliff,order:7,cast_id:17,profile_path:/1Ox63ukTd2yfOf1LVJOMXwmeQjO.jpg},{id:19860,name:Karl Yune,character:Tak Mashido,order:8,cast_id:18,profile_path:/qK315vPObCNdywdRN66971FtFez.jpg},{id:111206,name:Olga Fonda,character:Farra Lemkova,order:9,cast_id:19,profile_path:/j1qabOHf3Pf82f1lFpUmdF5XvSp.jpg},{id:53176,name:John Gatins,character:Kingpin,order:10,cast_id:41,profile_path:/A2MqnSKVzOuBf8MVfNyve2h2LxJ.jpg},{id:1126350,name:Sophie Levy,character:Big Sister,order:11,cast_id:42,profile_path:null},{id:1126351,name:Tess Levy,character:Little Sister,order:12,cast_id:43,profile_path:null},{id:1126352,name:Charlie Levy,character:Littlest Sister,order:13,cast_id:44,profile_path:null},{id:187983,name:Gregory Sims,character:Bill Panner,order:14,cast_id:45,profile_path:null}],crew:[{id:58726,name:Leslie Bohem,department:Writing,job:Screenplay,profile_path:null},{id:53176,name:John Gatins,department:Writing,job:Screenplay,profile_path:/A2MqnSKVzOuBf8MVfNyve2h2LxJ.jpg},{id:17825,name:Shawn Levy
You're searching from the first occurrence of "name:" until the "department:Directing" with everything in between.
Instead, you need to restrict what can be between the two strings. Here for example I'm saying that the characters that make up the name can only be alphanumeric or a space:
string.match(fixstrdirector,"name:([%w ]+),department:Directing")
Alternatively, given that there's a comma separating the parameters, a better approach would be to search for "name:" followed by any characters other than a comma, followed by "department:Directing":
string.match(fixstrdirector,"name:([^,]+),department:Directing")
Of course that wouldn't work if the name had a comma it in!
Lua patterns provides - modifier for tasks as you have above. As stated on PiL - Section 20.2:
The + modifier matches one or more characters of the original class.
It will always get the longest sequence that matches the pattern.
Like *, the modifier - also matches zero or more occurrences of
characters of the original class. However, instead of matching the
longest sequence, it matches the shortest one.
Next, when you are using . to match, it'll find any and all characters satisfying the pattern. Therefore, you'll get the result from first occurence of name until the ,department:Directing is found. Since you know that it is a JSON data, you can try to match for [^,]; that is, non-comma characters.
So, for your case try:
local tAllNames = {}
for sName in fixstrdirector:gmatch( "name:([^,]-),department:Directing" ) do
tAllNames[ #tAllNames + 1 ] = sName
end
and all your required names will be stored in the table tAllNames. An example of the above can be seen at codepad.

Resources