Matching function name and arguments using regex - javascript

I have some strings in the following pattern
'walkPath(left, down, left)'
To extract the function name alone, and the arguments in an another array, i used those regular expressions:
const str = 'walkPath(left, down, left)'
const functionNameRegex = /[a-zA-Z]*(?=\()/
console.log(str.match(functionNameRegex)) //outputs ['walkPath'] ✅✅
const argsRegex = /(?![a-zA-Z])([^,)]+)/g
console.log(str.match(argsRegex)) //outputs [ '(left', ' down', ' left' ]
the first one worked fine. In the second regex, the '(' from from '(left' should be excluded, so it should be 'left'

Try this one:
/(?<=\((?:\s*\w+\s*,)*\s*)\w+/g
const str = 'walkPath(left, down, left)'
const functionNameRegex = /[a-zA-Z]*(?=\()/
console.log(str.match(functionNameRegex))
const argsRegex = /(?<=\((?:\s*\w+\s*,)*\s*)\w+/g
console.log(str.match(argsRegex))
It is not very restricted, if you really want to be safe, you can try:
/(?<=\w+\s*\((?:\s*\w+\s*,\s*)*\s*)\w+(?=\s*(?:\s*,\s*\w+\s*)*\))/g

Use this regular expression for getting the arguments:
const argsRegex = /\(\s*([^)]+?)\s*\)/
For getting the arguments in an array:
const str = 'walkPath(left, down, left)'
const argsRegex = /\(\s*([^)]+?)\s*\)/
let res = str.match(argsRegex)
let args = res[1].split(", ")

Related

Get function names from specific string

I have string with slash separated contains function names.
e.g.
my_doc/desktop/customer=getCustomer()/getCsvFileName()/controller=getControllerName()
Within above string I want only function name i.e. getCustomer(), getControllerName() & getCsvFileName()
I searched some regex like:
let res = myString.match(/(?<=(function\s))(\w+)/g);
but its returning result as null.
Update:
Now I want to get function names without parentheses () i.e. getCustomer, getControllerName & getCsvFileName
Please help me in this
const str = "my_doc/desktop/customer=getCustomer()/getCsvFileName()/controller=getControllerName()"
let tokens = [];
for (element of str.split("/"))
if (element.endsWith("()"))
tokens.push(element.split("=")[1] ?? element.split("=")[0])
console.log(tokens);
General idea: split the string along slashes, and for each of these tokens, if the token ends with () (as per Nick's suggestion), split the token along =. Append the second index of the token split along = if it exists, otherwise append the first.
A "smaller" version (using purely array methods) could be:
const str = "my_doc/desktop/customer=getCustomer()/getCsvFileName()/controller=getControllerName()"
let tokens = str.split("/")
.filter(element => element.endsWith("()"))
.map(element => element.split("=")[1] ?? element.split("=")[0]);
console.log(tokens);
You can split the string that has parentheses () first like /.*?\([^)]*\)/g.
This will give array of results, and after that you can iterate the array data and for each item, you can split the = and / before function name with the help of item.split(/=|\//).
Then push the filtered function name into empty array functionNames.
Working Example:
const string = `my_doc/desktop/customer=getCustomer()/getCsvFileName()/controller=getControllerName()`;
const functionNames = [];
string.match(/.*?\([^)]*\)/g).forEach(item => {
const splitString = item.split(/=|\//);
const functionName = splitString[splitString.length - 1];
functionNames.push(functionName);
});
console.log(functionNames);
As per, MDN docs the match() method returns null if it does not find a match for the provided regex in the provided search string.
The regular expression which you have provided,/(?<=(function\s))(\w+)/g matches any word that has 'function ' before it. (NOTE: a space after the word function)
Your search string my_doc/desktop/customer=getCustomer()/getCsvFileName()/controller=getControllerName() does not include 'function ' before any characters. That is why you got null as result of match() method.
let yourString = 'my_doc/desktop/customer=getCustomer()/getCsvFileName()/controller=getControllerName()';
let myReferenceString = 'SAMPLETEXTfunction sayHi()/function sayHello()';
let res = yourString.match(/(?<=(function\s))(\w+)/g);
let res2 = myReferenceString.match(/(?<=(function\s))(\w+)/g);
console.log("Result of your string", res);
console.log("Result of my string", res2);
My solution here,
let myreferenceString = 'my_doc/desktop/customer=getCustomer()/getCsvFileName()/controller=getControllerName()'
let res = myreferenceString.match(/((?<==)(\w+\(\)))|((?<=\/)(\w+\(\)))/g);
console.log("Result", res);
NOTE: I have used the 'Positive Look Behind regex operator', This is not supported in browsers like Safari and IE. Please do reasearch about this before considering this approach.

Call Substring multiple times

I have a string and I want to remove this data like this \(f(x) = (a+b)\)
so i am thinking to get all subsstring and then make some operation on array. But it is giving me only one stripedHtml. So not able to get how to clean it. Just wants to remove this equations.
Result will be : Here’s the evidence
const filter_data = `<p>\(f(x) = (a+b)\)</p><p>\(f(x) = (a+db)\)</p><p>\(f(x) = (a+d+c+b)\)</p>
<p>Here’s the evidence.</p>`
var strippedHtml = filter_data.substring(
filter_data.lastIndexOf("\(") + 1,
filter_data.lastIndexOf("\)")
);
console.log(strippedHtml)
JS has a replace method for this that accepts RegExp:
const filter_data = `<p>\(f(x) = (a+b)\)</p><p>\(f(x) = (a+db)\)</p><p>\(f(x) = (a+d+c+b)\)</p>
<p>Here’s the evidence.</p>`;
var strippedHtml = filter_data.replace(/\<.*?\(.*?>/g, "");
console.log(strippedHtml);
The RegExp searches for an < followed by a ( and then an > and replaces all appearances with an empty value.
In your string it will match two times and do a replace.
Maybe you have to modify the RegExp to fit your real string as it would also match text nodes containing ( but that's what I would do at this point with the given data.
You can use following regular expressions to obtain solution for only similar type of data you were provided
const filterData1 = `<p>\(f(x) = (a+b)\)</p><p>\(f(x) = (a+db)\)</p><p>\(f(x) = (a+d+c+b)\)</p><p>Here’s the evidence.</p>`
const filterData2 = `<p>\(f(x) = (a+b)\)</p><p>\(f(x) = (a+db)\)</p><p>\(f(x) = (a+d+c+b)\)</p><p>Here’s the evidence.</p><p>\(f(x) = (a+b)\)</p>`
const regEx1 = /<[^>]*>/g //regular expression to remove all html tags
const regEx2 = /\([^\)]*\)/g //regular expression to remove everything between \( and \)
const regEx3 = /[=)]/g //regular expression to remove = and )
const result1 = filterData1.replace(regEx1,'').replace(regEx2,'').replace(regEx3,'').trim()
const result2 = filterData2.replace(regEx1,'').replace(regEx2,'').replace(regEx3,'').trim()
console.log("Result1 : ",result1);
console.log("Result2 : ",result2);

Convert End Quote to Apostrophe Javascript

The below two strings have different apostrophes. I am pretty stumped on how to convert them so that they are the same style (both are either slanted or both are either straight up and down). I have tried everything from enclosing it in `${}`` to regex expressions to remove and replace. I am not sure how it is being stored like this but when I try to search for string1 inside of string2 it doesn't recognize the index because (I believe) of the mismatch apostrophe. Has anyone run into this before?
//let textData = Father’s
//let itemData = Father's Day
const newData = currData.filter(item => {
let itemData = `${item.activityName.toUpperCase()}`;
let textData = `${text.toUpperCase()}`; //coming in slanted
let newItemData = itemData.replace(/"/g, "'");
let newTextData = textData.replace(/"/g, "'");
return newItemData.indexOf(newTextData) > -1;
});
first of all, your code won't run because you are not wrapping your string variables with ", ' or `, depending on the case.
if your string has ' you can use " or ` like this:
"Hello, I'm a dev"
or
"Hello, I`m a dev"
but you can not mix them if you have the same symbol, so this is not allowed:
'Hello, I`m a dev'
here you have a working example of your strings wrapped correctly and also replacing the values to match the strings.
note: please look that the index in this case is 0 because the whole string that we are looking matches from the 0 index to the length of the response1.
also I added a case if you want to get the partial string from string2 based on the match of string1
let string1 = "FATHER’S"
let string2 = "FATHER'S DAY: FOR THE FIXER"
const regex = /’|'/;
const replacer = "'";
let response1 = string1.replace(regex, replacer);
let response2 = string2.replace(regex, replacer);
console.log(response1);
console.log(response2);
console.log("this is your index --> ", response2.indexOf(response1));
console.log("string 2 without string 1 -->", response2.slice(response2.indexOf(response1) + response1.length, response2.length))
You could do a search using a regex, allowing for whatever apostrophe variations you expect:
let string1 = "FATHER’S"
let string2 = "FATHER'S DAY: FOR THE FIXER"
const regex = string1.split(/['’"`]/).join("['’\"`]")
//console.log(regex);
const r = new RegExp(regex)
console.log(string2.search(r)); //comes back as 0

Could a regular expression be used to find text between pairs of delimiters

I need to parse an email template for custom variables that occur between pairs of dollar signs, e.g:
$foo$bar$baz$foo$bar$baz$wtf
So I would want to start by extracting 'foo' above, since it comes between the first pair (1st and 2nd) of dollar signs. And then skip 'bar' but extract 'baz' as it comes between the next pair (3rd and 4th) of dollar signs.
I was able to accomplish this with split and filter as below, but am wondering, if there's a way to accomplish the same with a regular expression instead? I presume some sort of formal parser, recursive or otherwise, could be used, but that would seem like overkill in my opinion
const body = "$foo$bar$baz$foo$bar$baz$wtf";
let delimitedSegments = body.split('$');
if (delimitedSegments.length % 2 === 0) {
// discard last segment when length is even since it won't be followed by the delimiter
delimitedSegments.pop();
}
const alternatingDelimitedValues = delimitedSegments.filter((segment, index) => {
return index % 2;
});
console.log(alternatingDelimitedValues);
OUTPUT: [ 'foo', 'baz', 'bar' ]
Code also at: https://repl.it/#dexygen/findTextBetweenDollarSignDelimiterPairs
Just match the delimiter twice in the regexp
const body = "$foo$bar$baz$foo$bar$baz$wtf";
const result = body.match(/\$[^$]*\$/g).map(s => s.replace(/\$/g, ''));
console.log(result);
You could use this regex /\$\w+\$/g to get the expected output'
let regex = /\$\w+\$/g;
let str = '$foo$bar$baz$foo$bar$baz$wtf';
let result = str.match(regex).map( item => item.replace(/\$/g, ''));
console.log(result);
You can use capturing group in the regex.
const str1 = '$foo$bar$baz$foo$bar$baz$wtf';
const regex1 = /\$(\w+)\$/g;
const str2 = '*foo*bar*baz*foo*bar*baz*wtf';
const regex2 = /\*(\w+)\*/g;
const find = (str, regex) =>
new Array(str.match(regex).length)
.fill(null)
.map(m => regex.exec(str)[1]);
console.log('delimiters($)', JSON.stringify(find(str1, regex1)));
console.log('delimiters(*)', JSON.stringify(find(str2, regex2)));

Substring from the end in generic way in javascript

Assume we have such strings.
const del = 'Deleted'
const str1 = 'clean.Deleted'
const str2 = 'get.clean.Deleted'
const str3 = 'cl.Deleted'
And I need return every time str1, str2,str3 without .Deleted
It is work for me:
any_string.substr(0, (any_string.length - del.length-1))
Do we have a more generic way?
If .Deleted is always .Deleted, then string.replace
const newString = oldString.replace('.Deleted', '')
You can replace that with RegExp if you only want .Deleted that happens at the end.
const newString = oldString.replace(/\.Deleted$/, '')
To achieve expected result, use slice with negative value for slicing from last(.Deleted length is 8, so use -8)
str.slice('.Deleted',-8)
JS:
const del = 'Deleted'
const str1 = 'clean.Deleted'
const str2 = 'get.clean.Deleted'
const str3 = 'cl.Deleted'
console.log(str1.slice('.Deleted',-8))
console.log(str2.slice('.Deleted',-8))
console.log(str3.slice('.Deleted',-8))
Note: This solution works only if the .Deleted is always at the last part of the string

Categories

Resources