How would I make the following case insensitive?
if ($(this).attr("href").match(/\.exe$/))
{
// do something
}
Put an i after the closing slash of the regex.
So your code would look like this:
if ($(this).attr("href").match(/\.exe$/i))
With /i modifier:
if ($(this).attr("href").match(/\.exe$/i))
{
// do something
}
Another option would be to simply manipulate the case to what you want.
It appears as though you are trying to match against lowercase characters.
So you could do this:
if ($(this).attr("href").toLowerCase().match(/\.exe$/)) {
// do something
}
In fact, you could use .indexOf() instead of a regex if you wanted.
if ($(this).attr("href").toLowerCase().indexOf('.exe') > -1) {
// do something
}
Of course, this would match .exe in the middle of the string as well, if that's an issue.
Finally, you don't really need to create a jQuery object for this. The href property is accessible directly from the element represented by this.
if ( this.href.toLowerCase().match(/\.exe$/) ) {
// do something
}
if ($(this).attr("href").match(/\.exe$/i))
{
// do something
}
Unlike the match() function, the test() function returns true or false and is generally preferred when simply testing if a RegEx matches. The /i modifier for case insensitive matching works with both functions.
Example using test() with /i:
const link = $('a').first();
if (/\.exe$/i.test(link.attr('href')))
$('output').text('The link is evil.');
Fiddle with the code:
https://jsfiddle.net/71tg4dkw
Note:
Be aware of evil links that hide their file extension, like:
https://example.com/evil.exe?x=5
Documentation for test():
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
Related
I'm unable to determine if there is an implicit variable for match results in javascript.
The resulting code which I'm looking for is this:
if(line.match(/foo{bar}/)) {
console.log(bar_variable)
}
the referenced ^ bar_variable should contain the match group result.
Is there anything like this?
No, there is not. String.match() returns:
An Array whose contents depend on the presence or absence of the global (g) flag, or null if no matches are found.
So you could do something like:
if (bar_variable = line.match(/foo{bar}/)) {
console.log(bar_variable)
}
To avoid a global symbol you could do something like this, but it does make it a bit uglier:
{
let bar_variable;
if (bar_variable = line.match(/foo{bar}/)) {
console.log(bar_variable);
}
}
As far as I know you can't do if (let x = ...) but I could be wrong.
I have a basic replace function, but I need it to perform a global replace, as it seems to be stopping on the first instance. I do not want to do it with a Regex. Applying the global attribute seems easy enough in most examples, but I am passing in a variable as the value to be replaced, and /g is having no impact. What am I doing wrong? Here is the example without the /g:
test string
"Why is my ^%friend so ^%? Maybe I need a ^!% one, abrand^!% one"
Simple replace function
function translate(oddStr) {
var tagDictionary = {};
tagDictionary['^%'] = 'odd';
tagDictionary['^!%'] = 'new';
Object.keys(tagDictionary).forEach( function (tag) {
oddStr = oddStr.replace(tag, tagDictionary[tag]);
});
return oddStr;
};
This function returns the first instance of each replaced, as expected. How can I apply /g to the tag variable in the forEach?
Use a split-join combo like this:
oddStr = oddStr.split(tag).join(tagDictionary[tag]);
"Why is my ^% friend so ^%? Maybe I need a ^!% one, abrand ^!% one".replace(/\^%/g, 'odd').replace(/\^!%/g, 'new')
"Why is my odd friend so odd? Maybe I need a new one, abrand new one"
If you need to create the regular expression from string, you can use RegExp constructor: new RegExp('\\^%', 'g').
If you don't have control over the tag-dictionary and it is coming from some external resource, then you will have to properly escape the tags.
Instead of using adhoc symbols for templating you should ideally use something like lodash.template
You need to escape your regex special characters (^=Start of string)
function translate(oddStr) {
var tagDictionary = {
'\\^%' : "odd",
'\\^!%' : 'new'
};
Object.keys(tagDictionary).forEach( function (tag) {
var r = new RegExp(tag, "g");
oddStr = oddStr.replace(r, tagDictionary[tag]);
});
return oddStr;
};
console.log(translate("Why is my ^%friend so ^%? Maybe I need a ^!% one, a brand ^!% one"));
il8n = {
'en-us':{
hello:"Hello Everyone",
goodbye:"See ya later",
welcome:"Hello how are you?",
design:"Kandi Designs"
}
};
function translate(){
var userLang = navigator.language || navigator.userLanguage;
var body = document.body || document.getElementsByTagName('body')[0];
var html = body.innerHTML;
body.innerHTML = body.innerHTML.replace(/({T_(.*?)})/g, il8n[userLang.toLowerCase()][$1.replace(/{T_|},'').toLowerCase()]);
}
translate();
Basically what I want to do is get rid of {T_Hello} to Hello Everyone but since I suck at regex my capture groups and using $1 I can't get this correctly. Can anyone assist in this a wee bit?
You have the right idea. $1, however, is not a variable where you use it. Change the second argument to replace to this:
function (match, $1) {
return il8n[userLang.toLowerCase()][$1.toLowerCase()];
}
replace can take a function as an argument. Then, shorten the capture group in the regex to this:
/{T_(.*?)}/g
This saves you some unnecessary string processing inside the replace function. On an unrelated note, regarding performance, you might want the server to send the appropriate il8n object based on the Accept-Language header, or, even better, do the insertions itself instead of relying on flaky and slow client-side code (making it cacheable).
Based on your il8n object keys you could do this to check for T_ followed by any uppercase letters.
/T_([A-Z]+)/
You could add lowercase or numbers to it too:
/T_([A-Za-z0-9]+)/
This should work:
body.innerHTML = body.innerHTML.replace(
/({T_(.*?)})/g,
function (s) { return il8n [userLang.toLowerCase()] [s.replace(/{T_|}/g,'').toLowerCase()]; }
);
The second argument of replace() can be a string or a function that takes so many arguments as there are ()-groups in the regular expression, which in your case is one.
Indeed, if you write
s.replace (/a/g, 'b')
then, obviously, replace() receives two strings. However, if you write
s.replace (/a/g, f(x))
then again, replace() receives two strings, the second being the string returned from f(x), so if f(x) returns 'b', then the two expressions above are equivalent. Since f(x) is executed before replace() has a chance to see it, it cannot use the special variables like $1, since at the point of call they are not defined.
If you want the code to be executed by replace(), then it should be executable code:
replace (/a/g, function (x) { return ' [' + x + '] found! '; } )
so that at the point of call, the function object is formed and this function is called inside replace with the argument $1 each time (note the global modifier g in the regex).
Note that your code will only work if placed below the text or called onload(), not above the text:
<body>
{T_hello} reader!
<script>
your code
</script>
<body>
works, but
<body>
<script>
your code
</script>
{T_hello} reader!
<body>
doesn't, because when it is executed, there is nothing still in <body>. The best place to call it is in <body onload='translate()'>.
I also corrected a typo in your code: s.replace(/{T_|} should be s.replace(/{T_|}/.
And another error in your code is: s.replace(/{T_|}/ should be s.replace(/{T_|}/g, because it is supposed to make two replacements, not one.
I need to add a variable inside a Character Class when using javascript regular expression. What I tried did not work. What the correct syntax for accomplishing this.
For example,
if(/[variable]/.test(Log))
{
}
You can use the following syntax
var re = new RegExp(variable);
and then use
re.test(Log)
Try this instead:
var regex = new RegExp(variable);
if(regex.test(Log)){
// your logic
}
Hope this will help !!
a='.*'
var patt=new RegExp(a);
patt.test('asdsd')
Actually,
if(/[variable]/.test(Log)) {
}
Is equivalent to:
if(new RegExp("["+variable+"]").test(Log)) {
}
Explanation:
Whenever you use a regex with the // notation, such as:
/[\d*]"+/
You can use the RegExp object and pass the regex as a escaped string. This way, the above regex is equivalent to:
new RegExp("[\\d*]\"+")
The modifiers can be passed as second argument. So that /anything/gm is the same as new RegExp("anything", "gm").
When I want to replace some parts of a string, should I call replace directly like this?
var r1 = /"\+((:?[\w\.]+)(:?(:?\()(:?.*?)(:?\))|$){0,1})\+"/g;
arg = arg.replace(r1, function(outer, inner){
return eval(inner);
});
Or test for a match first, and then replace if it's a hit, like this?
var r1 = /"\+((:?[\w\.]+)(:?(:?\()(:?.*?)(:?\))|$){0,1})\+"/g;
if (r1.test(arg)) {
arg = arg.replace(r1, function(outer, inner){
return eval(inner);
});
}
I guess this boils down to how the string.replace(regex, string) function works. Will it go into my callback even if there is no match, or will it then simply return arg? In that case I assume the calling replace directly is the right way to go to avoid having the regex engine match the string twice?
You don have to use test. The function in replace only executed when a match occurs.
No matches: No function (eval) call
1 match: 1 call
2 matches: 2 calls
etc.
Also, why are you using eval? eval executes the parameter, as if it's a JavaScript expression. Since you know the input format, it's likely that you're able to achieve the same behaviour without eval.