Using javascript regular expressions, how do you match one character while ignoring any other characters that also match?
Example 1: I want to match $, but not $$ or $$$. Example 2: I want to match $$, but not $$$.
A typical string that is being tested is, "$ $$ $$$ asian italian"
From a user experience perspective, the user selects, or deselects, a checkbox whose value matches tags found in in a list of items. All the tags must be matched (checked) for the item to show.
function filterResults(){
// Make an array of the checked inputs
var aInputs = $('.listings-inputs input:checked').toArray();
// alert(aInputs);
// Turn that array into a new array made from each items value.
var aValues = $.map(aInputs, function(i){
// alert($(i).val());
return $(i).val();
});
// alert(aValues);
// Create new variable, set the value to the joined array set to lower case.
// Use this variable as the string to test
var sValues = aValues.join(' ').toLowerCase();
// alert(sValues);
// sValues = sValues.replace(/\$/ig,'\\$');
// alert(sValues);
// this examines each the '.tags' of each item
$('.listings .tags').each(function(){
var sTags = $(this).text();
// alert(sTags);
sSplitTags = sTags.split(' \267 '); // JavaScript uses octal encoding for special characters
// alert(sSplitTags);
// sSplitTags = sTags.split(' \u00B7 '); // This also works
var show = true;
$.each(sSplitTags, function(i,tag){
if(tag.charAt(0) == '$'){
// alert(tag);
// alert('It begins with a $');
// You have to escape special characters for the RegEx
tag = tag.replace(/\$/ig,'\\$');
// alert(tag);
}
tag = '\\b' + tag + '\\b';
var re = new RegExp(tag,'i');
if(!(re.test(sValues))){
alert(tag);
show = false;
alert('no match');
return false;
}
else{
alert(tag);
show = true;
alert('match');
}
});
if(show == false){
$(this).parent().hide();
}
else{
$(this).parent().show();
}
});
// call the swizzleRows function in the listings.js
swizzleList();
}
Thanks in advance!
Using javascript regular expressions, how do you match one character while ignoring any other characters that also match?
Example 1: I want to match $, but not $$ or $$$. Example 2: I want to match $$, but not $$$.
A typical string that is being tested is, "$ $$ $$$ asian italian"
From a user experience perspective, the user selects, or deselects, a checkbox whose value matches tags found in in a list of items. All the tags must be matched (checked) for the item to show.
function filterResults(){
// Make an array of the checked inputs
var aInputs = $('.listings-inputs input:checked').toArray();
// alert(aInputs);
// Turn that array into a new array made from each items value.
var aValues = $.map(aInputs, function(i){
// alert($(i).val());
return $(i).val();
});
// alert(aValues);
// Create new variable, set the value to the joined array set to lower case.
// Use this variable as the string to test
var sValues = aValues.join(' ').toLowerCase();
// alert(sValues);
// sValues = sValues.replace(/\$/ig,'\\$');
// alert(sValues);
// this examines each the '.tags' of each item
$('.listings .tags').each(function(){
var sTags = $(this).text();
// alert(sTags);
sSplitTags = sTags.split(' \267 '); // JavaScript uses octal encoding for special characters
// alert(sSplitTags);
// sSplitTags = sTags.split(' \u00B7 '); // This also works
var show = true;
$.each(sSplitTags, function(i,tag){
if(tag.charAt(0) == '$'){
// alert(tag);
// alert('It begins with a $');
// You have to escape special characters for the RegEx
tag = tag.replace(/\$/ig,'\\$');
// alert(tag);
}
tag = '\\b' + tag + '\\b';
var re = new RegExp(tag,'i');
if(!(re.test(sValues))){
alert(tag);
show = false;
alert('no match');
return false;
}
else{
alert(tag);
show = true;
alert('match');
}
});
if(show == false){
$(this).parent().hide();
}
else{
$(this).parent().show();
}
});
// call the swizzleRows function in the listings.js
swizzleList();
}
Thanks in advance!
Share Improve this question edited Jul 31, 2023 at 15:37 js2010 27.8k6 gold badges78 silver badges83 bronze badges asked Sep 28, 2012 at 21:22 user1003757user1003757 412 silver badges8 bronze badges 6-
2
Do you need it to match multiple occurrences of the single
$
character? Or just the first that matches? And can you post examples of the strings you're searching, and what the expected output should be for each of those strings? – David Thomas Commented Sep 28, 2012 at 21:24 - As in "aaa".replace(/a[^a]/, "")? – Wolfgang Kuehn Commented Sep 28, 2012 at 21:27
- usually it is something to the tune of (.*a[^a].*) – Benjamin Danger Johnson Commented Sep 28, 2012 at 21:29
- Thanks @amadeus, I don't know if I'm doing something wrong or just didn't explain it well enough. I've revised the question and the code. – user1003757 Commented Oct 9, 2012 at 18:05
- Thanks @BenjaminDangerJohnson, I don't know if I'm doing something wrong or just didn't explain it well enough. I've revised the question and the code. – user1003757 Commented Oct 9, 2012 at 18:06
4 Answers
Reset to default 4Normally, with regex, you can use (?<!x)x(?!x)
to match an x
that is not preceded nor followed with x
.
With the modern ECMAScript 2018+ pliant JS engines, you may use lookbehind based regex:
(?<!\$)\$(?!\$)
See the JS demo (run it in supported browsers only, their number is growing, check the list here):
const str ="$ $$ $$$ asian italian";
const regex = /(?<!\$)\$(?!\$)/g;
console.log( str.match(regex).length ); // Count the single $ occurrences
console.log( str.replace(regex, '<span>$&</span>') ); // Enclose single $ occurrences with tags
console.log( str.split(regex) ); // Split with single $ occurrences
\bx\b
Explanation: Matches x between two word boundaries (for more on word boundaries, look at this tutorial). \b
includes the start or end of the string.
I'm taking advantage of the space delimiting in your question. If that is not there, then you will need a more plex expression like (^x$|^x[^x]|[^x]x[^x]|[^x]x$)
to match different positions possibly at the start and/or end of the string. This would limit it to single character matching, whereas the first pattern matches entire tokens.
The alternative is just to tokenize the string (split it at spaces) and construct an object from the tokens which you can just look up to see if a given string matched one of the tokens. This should be much faster per-lookup than regex.
Something like that:
q=re.match(r"""(x{2})($|[^x])""", 'xx')
q.groups() ('xx', '')
q=re.match(r"""(x{2})($|[^x])""", 'xxx')
q is None True
I simplified down to this. You have to negate both sides. I'm using powershell, but it should work in javascript. In regex, the dollarsign has to be escaped with a backslash.
'hi $ hi' | select-string '[^\$]\$[^\$]'
hi $ hi
'hi $$ hi' | select-string '[^\$]\$[^\$]'
# nothing
Actually something more plicated is needed, if the dollar is the only thing on the line. (Ooo, regex101. has a debugger.) I was doing this for '&' but not '&&' in .bat files, and '&' doesn't need a backslash.
'$' | select-string '(^|[^\$])\$($|[^\$])'
$
'$$' | select-string '(^|[^\$])\$($|[^\$])'
# nothing