How can I call a function from regular expression matches in javascript - javascript

I have a regular expression and I'm wondering if I can use all matches as an argument for a function. For example, let's say that I have a data set
Hello heelo hhhheEEeloo eelloooo
and a regular expression
/[Hh]{1,}[Ee]{1,}[Ll]{1,}[Oo]{1,}/
which would match
Hello heelo hhhheEEeloo
how can I get a javascript function to take in each match as an argument, for example
function isHello(arg) {
if (arg == 'Hello') { return 1 }
else { return 0}
}

Use .replace with a callback
"Hello heelo hhhheEEeloo eelloooo".replace(/[Hh]{1,}[Ee]{1,}[Ll]{1,}[Oo]{1,}/g,function(match){
//Your function code here
return match;
})
Or a more trivial example:
var count=0;
"aaaaaaa".replace(/a/g,function(match){
console.log("I matched another 'a'",count++);
// just to not replace anything, technically this doesn't matter
//since it doesn't operate on the actual string
return match;
});
Fiddle

var string = "Hello heelo hhhheEEeloo eelloooo",
regex = /[Hh]{1,}[Ee]{1,}[Ll]{1,}[Oo]{1,}/g,
fn = function(arg){
if (arg == 'Hello')
return 1;
return 0
};
string.match(regex).forEach(fn);
Notice the g flag added to the regex to match in order to give the desired match.

Here is an example using match():
var s = "Hello heelo hhhheEEeloo eelloooo";
s.match(/[Hh]{1,}[Ee]{1,}[Ll]{1,}[Oo]{1,}/g).forEach(function(entry) {
// your function code here, the following is just an example
if (entry === "Hello")
console.log("Found Hello!");
else
console.log(entry + " is not Hello");
return;
});
Example: http://jsfiddle.net/wTMuF/

Related

Replace matches with regex

I am trying to replace matches of text between dollar signs.
So the text $match$ inside Some text and $some text that matches$. should be replaced.
I have tried
text.replace(/\$.*?\$/g, function (match) {
return '_' + match + '_';
}
This works. The problem is that I want to do evaluate the match inside this function, but sometimes the evaluation didn't work, and in these cases I just want to return the original match. So it is something like
text.replace(/\$.*?\$/g, function (match) {
try {
return evaluate(match);
} catch (e) {
return match;
}
}
But with my current regex, the match contains the dollar signs from the original text. I want it to omit the dollar signs, but if the evaluation fails, then I want the original dollar signs back.
What I could do is
text.replace(/\$.*?\$/g, function (match) {
try {
return evaluate(match.replace(/\$/g, ''));
} catch (e) {
return match;
}
}
but isn't it possible in a more elegant way?
Something like this might do:
const evaluate = function(str) {
if (str && str.startsWith("t")) {return str.toUpperCase();}
throw "Gotta hava a 'T'";
};
"ab$test$cd $something$ that is $tricky$.".replace(/\$([^$]*)\$/g;, function(str, match) {
try {
return evaluate(match);
} catch(e) {
return str;
}
}); //=> "abTESTcd $something$ that is TRICKY."
But I agree with the comment that you might be better returning a different signal (undefined? null?) from evaluate rather than throwing for this case. And then the function body could simply be something like:
return evaluate(match) || str;
The point is the capturing group in the regex: /\$([^$]*)\$/g;, which becomes a parameter to the replacement function.

Make a function in .replace()

I have the following code that uses a regex:
var mystring = "<<cool>> <<stuff>>"
var regexString = /<<([^\:]{0,})>>/gi
mystring.replace(regexString, "$1")
I would like to be able to replace the string based on the text I get back on the capture group. Something like:
var mystring = "<<cool>> <<stuff>>"
var regexString = /<<([^>]{1,})>>/gi
mystring.replace(regexString, function(var0) { //var0 being the text from the capture group
if(var0 == "cool") {
console.log("got cool")
} else {
console.log("didn't get cool")
}
})
Is there someway to do this?
Yes, you can definitely use a function as a second argument of .replace(). For example:
mystring.replace(regexString, function(match, group1) {
// do anything with group1 here
});
Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace

Replace function in javascript is not consistent when function is provided as then second parameter

function function1(format) {
var regexp = /[<>]/g;
//Here the parameters are matched string,
//the position and the original text
var str = format.replace(regexp,function(match,position,originalText){
return match;
});
return str;
}
function function2(format) {
var regexp = /:(\w+)/g;
//Here the parameters are matched string,
//something like stripped string, and the position
var str = format.replace(regexp,function(match,stripped,position){
return match;
});
return str;
}
console.log(function1('<hello>'));
console.log(function2(':url :method'));
I got the first function from #Professional JavaScript for Web Developers#, and the second function from #NodeJS in Action#.
You can see that the call back function for replace is not consistent. Why?
The callback in function2 could be written with a 4th argument to appear less confusing and more consistent with the first callback in your examples:
function function2(format) {
var regexp = /:(\w+)/g;
var str = format.replace(regexp,function(match,submatch,position,originalText){
return match;
});
return str;
}
Look at how the callback in replace can be defined: it accepts a number of arguments >= 3. The optional arguments are used only if your regex contains submatches, and they correspond to the nth parenthesized submatch string:
function(match, [p1, p2, ...], offset, string) { ... }
Whats sounds confusing, I guess, is that they are placed in the middle. Also note that the callback function will be invoked multiple times for each full match to be replaced, if the regular expression in the first parameter is global (which is true in your example).

return first element not empty element of array

I have a string that can have words and spaces.
I want to return the first word inside the string.
My method was:
apply .split(' ') to it to remove the white spaces.
do .filter(function(el){ return (el != '') }
get the first element by using [0]
Is there a more optimized way to this? Maybe regex?
My code:
var string = " foo bar ";
function getFirst(str) {
var separatedString = str.split(' ');
separatedString = separatedString.filter(function (el) {
return (el != '')
})
return separatedString[0];
}
Fiddle
Probably closest equivalent of your code will be this line:
var word1 = s.replace(/\s*(\S+).*/, '$1');
Since you're splitting by space so this code will just grab the very first non-space substring from given input.
You could use trim and split on multiple spaces and use string.length in your filter:
function getFirst(str) {
var separatedString = str.split(/\s+/).filter( function (el) {
return el.length;
});
return separatedString[0];
}
getFirst(' foo-bar foo bar bar#foo '); //=> 'foo-bar'
You can do
var firstWord = string.match(/\S+/)[0];

Convert hyphens to camel case (camelCase)

With regex (i assume) or some other method, how can i convert things like:
marker-image or my-example-setting to markerImage or myExampleSetting.
I was thinking about just splitting by - then convert the index of that hypen +1 to uppercase. But it seems pretty dirty and was hoping for some help with regex that could make the code cleaner.
No jQuery...
Try this:
var camelCased = myString.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
The regular expression will match the -i in marker-image and capture only the i. This is then uppercased in the callback function and replaced.
This is one of the great utilities that Lodash offers if you are enlightened and have it included in your project.
var str = 'my-hyphen-string';
str = _.camelCase(str);
// results in 'myHyphenString'
You can get the hypen and the next character and replace it with the uppercased version of the character:
var str="marker-image-test";
str.replace(/-([a-z])/g, function (m, w) {
return w.toUpperCase();
});
Here's my version of camelCase function:
var camelCase = (function () {
var DEFAULT_REGEX = /[-_]+(.)?/g;
function toUpper(match, group1) {
return group1 ? group1.toUpperCase() : '';
}
return function (str, delimiters) {
return str.replace(delimiters ? new RegExp('[' + delimiters + ']+(.)?', 'g') : DEFAULT_REGEX, toUpper);
};
})();
It handles all of the following edge cases:
takes care of both underscores and hyphens by default (configurable with second parameter)
string with unicode characters
string that ends with hyphens or underscore
string that has consecutive hyphens or underscores
Here's a link to live tests: http://jsfiddle.net/avKzf/2/
Here are results from tests:
input: "ab-cd-ef", result: "abCdEf"
input: "ab-cd-ef-", result: "abCdEf"
input: "ab-cd-ef--", result: "abCdEf"
input: "ab-cd--ef--", result: "abCdEf"
input: "--ab-cd--ef--", result: "AbCdEf"
input: "--ab-cd-__-ef--", result: "AbCdEf"
Notice that strings that start with delimiters will result in a uppercase letter at the beginning.
If that is not what you would expect, you can always use lcfirst.
Here's my lcfirst if you need it:
function lcfirst(str) {
return str && str.charAt(0).toLowerCase() + str.substring(1);
}
Use String's replace() method with a regular expression literal and a replacement function.
For example:
'uno-due-tre'.replace(/-./g, (m) => m[1].toUpperCase()) // --> 'unoDueTre'
Explanation:
'uno-due-tre' is the (input) string that you want to convert to camel case.
/-./g (the first argument passed to replace()) is a regular expression literal.
The '-.' (between the slashes) is a pattern. It matches a single '-' character followed by any single character. So for the string 'uno-due-tre', the pattern '-.' matches '-d' and '-t' .
The 'g' (after the closing slash) is a flag. It stands for "global" and tells replace() to perform a global search and replace, ie, to replace all matches, not just the first one.
(m) => m[1].toUpperCase() (the second argument passed to replace()) is the replacement function. It's called once for each match. Each matched substring is replaced by the string this function returns. m (the first argument of this function) represents the matched substring. This function returns the second character of m uppercased. So when m is '-d', this function returns 'D'.
'unoDueTre' is the new (output) string returned by replace(). The input string is left unchanged.
This doesn't scream out for a RegExp to me. Personally I try to avoid regular expressions when simple string and array methods will suffice:
let upFirst = word =>
word[0].toUpperCase() + word.toLowerCase().slice(1)
let camelize = text => {
let words = text.split(/[-_]/g) // ok one simple regexp.
return words[0].toLowerCase() + words.slice(1).map(upFirst)
}
camelize('marker-image') // markerImage
Here is my implementation (just to make hands dirty)
/**
* kebab-case to UpperCamelCase
* #param {String} string
* #return {String}
*/
function toUpperCamelCase(string) {
return string
.toLowerCase()
.split('-')
.map(it => it.charAt(0).toUpperCase() + it.substring(1))
.join('');
}
// Turn the dash separated variable name into camelCase.
str = str.replace(/\b-([a-z])/g, (_, char) => char.toUpperCase());
Here is another option that combines a couple answers here and makes it method on a string:
if (typeof String.prototype.toCamel !== 'function') {
String.prototype.toCamel = function(){
return this.replace(/[-_]([a-z])/g, function (g) { return g[1].toUpperCase(); })
};
}
Used like this:
'quick_brown'.toCamel(); // quickBrown
'quick-brown'.toCamel(); // quickBrown
You can use camelcase from NPM.
npm install --save camelcase
const camelCase = require('camelcase');
camelCase('marker-image'); // => 'markerImage';
camelCase('my-example-setting'); // => 'myExampleSetting';
Another take.
Used when...
var string = "hyphen-delimited-to-camel-case"
or
var string = "snake_case_to_camel_case"
function toCamelCase( string ){
return string.toLowerCase().replace(/(_|-)([a-z])/g, toUpperCase );
}
function toUpperCase( string ){
return string[1].toUpperCase();
}
Output: hyphenDelimitedToCamelCase
is also possible use indexOf with recursion for that task.
input some-foo_sd_dsd-weqe
output someFooSdDsdWeqe
comparison ::: measure execution time for two different scripts:
$ node camelCased.js
someFooSdDsdWeqe
test1: 2.986ms
someFooSdDsdWeqe
test2: 0.231ms
code:
console.time('test1');
function camelCased (str) {
function check(symb){
let idxOf = str.indexOf(symb);
if (idxOf === -1) {
return str;
}
let letter = str[idxOf+1].toUpperCase();
str = str.replace(str.substring(idxOf+1,idxOf+2), '');
str = str.split(symb).join(idxOf !== -1 ? letter : '');
return camelCased(str);
}
return check('_') && check('-');
}
console.log(camelCased ('some-foo_sd_dsd-weqe'));
console.timeEnd('test1');
console.time('test2');
function camelCased (myString){
return myString.replace(/(-|\_)([a-z])/g, function (g) { return g[1].toUpperCase(); });
}
console.log(camelCased ('some-foo_sd_dsd-weqe'));
console.timeEnd('test2');
Just a version with flag, for loop and without Regex:
function camelCase(dash) {
var camel = false;
var str = dash;
var camelString = '';
for(var i = 0; i < str.length; i++){
if(str.charAt(i) === '-'){
camel = true;
} else if(camel) {
camelString += str.charAt(i).toUpperCase();
camel = false;
} else {
camelString += str.charAt(i);
}
}
return camelString;
}
Use this if you allow numbers in your string.
Obviously the parts that begin with a number will not be capitalized, but this might be useful in some situations.
function fromHyphenToCamelCase(str) {
return str.replace(/-([a-z0-9])/g, (g) => g[1].toUpperCase())
}
function fromHyphenToCamelCase(str) {
return str.replace(/-([a-z0-9])/g, (g) => g[1].toUpperCase())
}
const str1 = "category-123";
const str2 = "111-222";
const str3 = "a1a-b2b";
const str4 = "aaa-2bb";
console.log(`${str1} => ${fromHyphenToCamelCase(str1)}`);
console.log(`${str2} => ${fromHyphenToCamelCase(str2)}`);
console.log(`${str3} => ${fromHyphenToCamelCase(str3)}`);
console.log(`${str4} => ${fromHyphenToCamelCase(str4)}`);
You can also use string and array methods; I used trim to avoid any spaces.
const properCamel = (str) =>{
const lowerTrim = str.trim().toLowerCase();
const array = lowerTrim.split('-');
const firstWord = array.shift();
const caps = array.map(word=>{
return word[0].toUpperCase() + word.slice(1);
})
caps.unshift(firstWord)
return caps.join('');
}
This simple solution takes into account these edge cases.
Single word
Single letter
No hyphen
More than 1 hyphen
const toCamelCase = (text) => text.replace(/(.)([^-|$]*)[-]*/g, (_,letter,word) => `${letter.toUpperCase()}${word.toLowerCase()}`)

Categories

Resources