How can I run matched string as a variable in JavaScript? - javascript

I'm working on a very basic templating system and struggling.
Take this:
some useless text here but i want to replace %% this %% with the variable: object.this
This seems like it'd be easy, but I can't figure it out. Here's my code:
function loadTemplate(element, object) {
var regex = /%% (.*) %%/;
return $(element).html().replace(regex, eval("object.$1"));
}
I've tried a few different things. Currently the eval returns undefined. When I try eval("$1"), it gives me an uncaught reference error and tells me that $1 isn't defined.

You don't need eval as replace takes a callback function; do your logic there. The first parameter is the matched substring, the second one is the first capturing group match. Using bracket notation you can access the object's key dynamically with a string:
.replace(regex, function(_, a) {
return object[a];
});

Related

Looking for if null ignore - Regular Expressions - TypeError: Cannot read property '1' of null [duplicate]

I'm trying to pull the first occurence of a regex pattern from a string all in one statement to make my code look cleaner. This is what I want to do:
var matchedString = somestring.match(/some regex/g)[0];
I would expect this to be legal but it throws an exception:
Exception: somestring.match(...) is null
It seems like JS is trying to index the array before match is finsihed, as the array does provide atleast one match, so I don't expect it to be null.
I would like some insight in why it happens. Could it be a bug?
My machine is a PC running Arch Linux x86_64. The code is being executed within the scratchpad of firefox 32.0.3.
Thanks for your interest.
If somestring.match() finds no match, then it returns null.
And, null[0] throws an exception.
Since you are getting this exact exception, your regex is not being found in the content. Be very careful using the g flag on a match option in this way as it does not always do what you expect when you have submatches specified in the regex. Since it looks like you just want the first match anyway, you should probably remove the g option.
A safer way to code is:
var matches = somestring.match(/some regex/);
if (matches) {
// do something here with matches[0]
}
If you want to do it in one statement (and there's no particularly good reason why that is a good idea, see jfriend000's answer), then:
var firstMatchOrFalse = /pattern/.test(somestring) && somestring.match(/pattern/)[0];
and if you only want the first match, why the g flag?

Why isn't .replace() working on a large generated string from escodege.generate()?

I am attempting to generate some code using escodegen's .generate() function which gives me a string.
Unfortunately it does not remove completely the semi-colons (only on blocks of code), which is what I need it to do get rid of them myself. So I am using the the .replace() function , however the semi-colons are not removed for some reason.
Here is what I currently have:
generatedCode = escodegen.generate(esprima.parseModule(code), escodegenOptions)
const cleanGeneratedCode = generatedFile.replace(';', '')
console.log('cleanGeneratedCode ', cleanGeneratedCode) // string stays the exact same.
Am I doing something wrong or missing something perhaps?
As per MDN, if you provide a substring instead of a regex
It is treated as a verbatim string and is not interpreted as a regular expression. Only the first occurrence will be replaced.
So, the output probably isn't exactly the same as the code generated, but rather the first semicolon has been removed. To remedy this, simply use a regex with the "global" flag (g). An example:
const cleanGenereatedCode = escodegen.generate(esprima.parseModule(code), escodegenOptions).replace(/;/g, '');
console.log('Clean generated code: ', cleanGeneratedCode);

JavaScript - Understanding the role of a variable in a function passed as an argument

I'm trying to work with regular expressions, in particular I've to shuffle the middle content of a string. I found an example that fits my needs Here and the answer I'm studying is the one by Brian Nickel.
This is the code proposed by Brian Nickel in the question:
myStr.replace(/\b([a-z])([a-z]+)([a-z])\b/ig, function(str, first, middle, last) {
return first +
middle.split('').sort(function(){return Math.random()-0.5}).join('') +
last;
});
I'm very beginner in JavaScript and RegEx, I see here a function is passed as an argument, but I don't understand why there are four parameters, in particular I do not understand the first parameter str and why if I remove it, function doesn't work anymore correctly.
I now it's a silly question, but I don't found what I want on the Web, or maybe I don't know how to search properly. Thanks in advance
When using replace with RegExp, the function use as callback receive 1+n parameters where n are the match inside parenthesis.
The always come in that order :
The complete matched string.
The first parenthesis.
The second parenthesis.
Go on...
If you remove the str and the argument first become the matched string. So even if you don't use this argument, you need it!

How can I search for {{.*}} and replace with json

I am trying to create my own javascript simple template function
I want to create a html page that will look like this
<p>
{{HELLO_WORLD}}
<br />
{{MY_NAME_IS}}
</p>
and than with javascript to replace anything that is in {{}}
with a json var that will look like this
{HELLO_WORLD: "Hello World!", MY_NAME_IS: "My name is"}
I am a little confused about the right method to do this.
the point is to make a multilanguage web site, that way I load the json for the desired language.
thank's.
JavaScript supports regular expression-based find-and-replace, with functions for the replacement. So you can do this:
myInputString.replace( /\{\{([^\}]*)\}\}/g, function( s, v ) { return myJSON[v] } );
To explain:
replace takes 2 arguments. The first is a regular expression object. In this case we build one inline using JavaScript's /expression/flags syntax. It looks for 2 opening braces (which need to be escaped because they have special meaning in regular expressions) followed by any characters which are not a closing brace, followed by 2 closing braces. The g means "global", so that it will match all cases rather than just the first one.
When a match is found, the function will be called. The first argument (I called it s) is the full matched string (like "{{abc}}"), the second (I called it v) is set to the first bit in brackets (like "abc").
In real code, you should add error checking (variables which don't exist), and possibly convert to lowercase / whatever.
Full details on replace are here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace

Regex back reference, what I am missing?

I am writing a micro-templating script where parts of a string are replaced with object options. Here is a short example:
var person = {name:"Smith",age:43};
var string = "I am {name} and I am {age} years old";
document.write(string.replace(/{([\s\S]+?)}/g,(person['$1']||"")));
document.write("<br/>");
document.write(string.replace(/{([\s\S]+?)}/g
, function($0,$1){return person[$1]||"";}));
​Also in a JS Fiddle
The second expression works fine, but not the first one. Could anybody explain why? I thought $1 could be directly used as a back reference within a string.
$1, $2, ..., $& can only be used when they're part of a string value passed to replace:
string.replace(/{([\s\S]+?)}/g, '$1(matched)');
// result: "I am name(matched) and I am age(matched) years old"
But, the 1st snippet is effectively:
document.write(string.replace(/{([\s\S]+?)}/g,""));
That's because (person['$1']||"") is not a value that can be passed as-is. It's a property-lookup and logical-or that will be evaluated first and their resulting value -- "" -- will be what's actually passed to replace.
To be able to evaluate an expression after you have a match, you have to use a function to delay the evaluation, as you have in the 2nd snippet.
It makes sense to me, I mean if you look at this:
person['$1']
You're basically saying "give me the object $1 inside person" which in this case is undefined. I guess it tries to evaluate the object before the regex capture group. That's why you have the function replacement and it works, for this circumstances.
RegExp.replace method attempts to parse $n expressions (as well as $& and several others - look here for complete list) only within strings. But something like person['$1'] is not a string - it's an expression which may be (or may be not) evaluated to string. Only after this evaluation the backreference 'markers' will be parsed.
I suppose the callback in replace is the only quite normal way to go in your case.
You don't have single quotes around the $1 in the second regex.

Categories