Getting too many matches for regex - javascript

I wrote a regex tester in JS. However, it appears that for some regexes, I get multiple matches.
For example, if for the content hello, world, the regex hello.* is given, the it is reported to match hello, world. However, if the regex is now set to (hello|goodbye).* then the reported matches are hello, world and hello, whereas it should be hello, world only.
<!DOCTYPE html>
<html>
<head>
<title>Regex tester</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<script type="text/javascript">
function resetform() {
document.getElementById("results").innerHTML = "";
}
function escapetags(str) {
return (str.replace('&','&').replace('<', '<').replace('>', '>'));
}
function check() {
if (!document.form1.re.value) {
document.getElementById("results").innerHTML = '<p style="color:red"><b>Error: No regular expression specified</b></p>';
return;
}
if (!document.form1.str.value) {
document.getElementById("results").innerHTML = '<p style="color:red"><b>Error: No content specified</b></p>';
return;
}
var pattern,
modifiers = "";
if (document.form1.nocase.checked) {
modifiers = "i";
}
if (document.form1.global.checked) {
modifiers = modifiers + "g";
}
try {
if (modifiers) {
pattern = new RegExp(document.form1.re.value, modifiers);
} else {
pattern = new RegExp(document.form1.re.value);
}
} catch (excpt) {
document.getElementById("results").innerHTML = '<p style="color:red"><b>Error: Invalid regular expression</b></p>';
return;
}
var matches = pattern.exec(document.form1.str.value);
if (matches == null) {
document.getElementById("results").innerHTML = '<p><b>Regular expression did not match with content<b></p>';
} else {
document.getElementById("results").innerHTML = '<p><b>Regular expression matched with content</b></p><p>Matches:</p>';
for (var index = 0; index < matches.length; index++) {
document.getElementById("results").innerHTML += escapetags(matches[index]) + '<br>';
}
}
}
</script>
<h1>Regex tester</h1>
<form name="form1">
<p>Regex:</p>
<input type="text" name="re" size="65"><br>
<input type="checkbox" name="nocase">Case insensitive
<input type="checkbox" name="global">Global
<p>Content:</p>
<textarea name="str" rows="8" cols="65"></textarea><br><br>
<input type="button" value="Check" onclick="check();">
<input type="button" value="Reset" onclick="reset();resetform();">
</form>
<div id="results"></div>
</body>
</html>
Can anyone help me find the problem in my code?
Thanks in advance.

"(hello|goodbye). then the reported matches are hello, world and hello*"
No, the second "match" is just the result of your capturing group (what's between the parenthesis). Ignore it, or make the group non-capturing: (?:hello|goodbye)

The .exec() method of the JavaScript regex will return the entire matched string as the first element and then any captured groups as subsequent elements. When you use the regex:
(hello|goodbye).*
The brackets define a capture group, so your returned array will be
[0] = hello, world
[1] = hello
As Loamhoof suggest below, you can add ?: to make a group non-capturing if that is not desirable.

I think you want something like this,
var a = new RegExp("hello, world"); //or your string
var b = "hello, world";
if(a.test(b)){
//do your stuff
}
else{
//do your stuff
}
it will only match for the given pattern.

Related

New to Javascript, could someone help me with this substring problem?

The below script returns the following into my html:
"3.9 °C {alarm,unackedAlarm}"
I would like to remove the "{alarm,unackedAlarm}" section so it just shows the temperature value. I believe I need to use a substring to achieve this but I cannot work out where to place it?
Thanks
<script src="https://requirejs.org/docs/release/2.3.6/minified/require.js" ></script>
require(['baja!', 'dialogs'], function (baja, dialogs) {
var sub = new baja.Subscriber();
sub.attach('changed', function(prop) {
if(prop.getName() === 'value');
{
document.getElementById("oat").innerHTML = ( this.get(prop));
}
});
baja.Ord.make('station:|slot:/BajaScriptExamples/Components/Ramp/out/value').get({ subscriber: sub});
});
'''
I would suggest using the regex approach just in case the number of characters change.
function extract(text) {
const pattern = /^(.*) {.*}$/g;
const match = [...text.matchAll(pattern)];
if (match.length == 0 || match[0].length == 0) {
console.error("text does not match");
return;
}
return match[0][1];
}
console.log(extract("3.9 °C {alarm,unackedAlarm}"));
The main idea here is to catch any string that follows this pattern (.*) {.*} and return what is in contained between the parenthesis (group).
The requirement of extracting specific part of a string can be done easily by using the split() function of Javascript.
Here are working examples using split:
Example 1: Split the string at blank spaces and print the first two parts.
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
var str = "3.9 °C {alarm,unackedAlarm}"
var result = str.split(" ")
document.getElementById("demo").innerHTML = (result[0] + " " + result[1])
</script>
</body>
</html>
Example 2: Split the string at '{' and print the first part.
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
var str = "3.9 °C {alarm,unackedAlarm}"
var result = str.split("{")
document.getElementById("demo").innerHTML = (result[0].trim())
</script>
</body>
</html>
Output:
3.9 °C
More information:
https://www.w3schools.com/jsref/jsref_split.asp

Word count in AngularJS

I am trying to write a quick program that counts the number of words in AngularJS. Basically a textarea in HTML and underneath it should display the number of words as the user inputs them.
So this is my HTML code:
<!doctype html>
<html ng-app>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.min.js"></script>
<script src="wordcount.js"></script>
</head>
<body>
<div ng-controller="wordCount">
<label>Copy and Paste your text:</label><br>
<textarea cols="80" rows="20" ng-model="mytext"></textarea>
<hr>
<span>{{wordCount()}} word(s)</span>
</div>
</body>
</html>
And here is my Javascript file called wordcount.js (to count the number of words in a given string):
function wordCount($scope) {
$scope.numberofwords = function(s) {
s = document.getElementById("mytext").value;
s = s.replace(/(^\s*)|(\s*$)/gi,"");
s = s.replace(/[ ]{2,}/gi," ");
s = s.replace(/\n /,"\n");
return s.split(' ').length;
}
}
I basically found the above on http://www.mediacollege.com/internet/javascript/text/count-words.html
So I have probably not fully understood how to use AngularJS (and the JS code is probably wrong too) to update the number of words instantly. Right now it doesn't show anything but "words".
Does anyone have an idea?
One of correct way is to use a $scope function:
<body ng-controller="WCController">
<h3>World count</h3>
<div>total words: <span ng-bind="countOf(myText)"></span></div>
<textarea ng-model="myText"></textarea>
</body>
and at the controller:
$scope.countOf = function(text) {
var s = text ? text.split(/\s+/) : 0; // it splits the text on space/tab/enter
return s ? s.length : '';
};
You can test this on plunker:
http://run.plnkr.co/Mk9BjXIUbs8hGoGm/
Solution
update a wordCount property when myText changes.
use simple regexp in a String.prototype.match call.
use this updated wordCount scope property in your template.
Code
Your watcher should look like something like that:
$scope.$watch('myText', function(text) {
// no text, no count
if(!text) {
$scope.wordCount = 0;
}
// search for matches and count them
else {
var matches = text.match(/[^\s\n\r]+/g);
$scope.wordCount = matches ? matches.length : 0;
}
});
Important note
Why computing the count in a watcher ?
To prevent this count from being computed on each digestion, the way it is when you use such a wordCount() method call in your template !

search for periods and randomly decide to add a word after the period 50% of the time

I am having a hard time trying to figure out how to search through a textarea and find the periods, after finding the periods I need to randomly decide if I should add "arrr" after the period this should be a 50/50 chance of having the word printed in there.
HELP ME Please!!! here's what i have going on so far, it's kind of a mess
document.getElementById("translate").onclick = function changed()
{
var outpara = document.getElementById("out")
var paragraph = document.getElementById("input").value;
paragraph = paragraph.toLowerCase();
while(paragraph.indexOf("hello")!== -1)
{
paragraph = paragraph.replace("hello", "Ahoy");
}
while(paragraph.indexOf("excuse me")!== -1)
{
paragraph = paragraph.replace("excuse me", "arrr");
}
while(paragraph.indexOf("sir")!== -1)
{
paragraph = paragraph.replace("sir", "matey");
}
while(paragraph.indexOf("madam")!== -1)
{
paragraph = paragraph.replace("madam", "proud beauty");
}
while(paragraph.indexOf("officer")!== -1)
{
paragraph = paragraph.replace("officer", "foul blaggart");
}
while(paragraph.indexOf("where is")!== -1)
{
paragraph = paragraph.replace("where is", "whar be");
}
while(paragraph.indexOf("can you help me find")!== -1)
{
paragraph = paragraph.replace("can you help me find", "know ye");
}
while(paragraph.indexOf("is that")!== -1)
{
paragraph = paragraph.replace("is that", "be that");
}
while(paragraph.indexOf("the")!== -1)
{
paragraph = paragraph.replace("the", "th'");
}
while(paragraph.indexOf("my")!== -1)
{
paragraph = paragraph.replace("my", "me");
}
while(paragraph.indexOf("your")!== -1)
{
paragraph = paragraph.replace("your", "yer");
}
while(paragraph.indexOf("restroom")!== -1)
{
paragraph = paragraph.replace("restroom", "head");
}
while(paragraph.indexOf("restaurant")!== -1)
{
paragraph = paragraph.replace("restaurant", "galley");
}
while(paragraph.indexOf("hotel")!== -1)
{
paragraph = paragraph.replace("hotel", "fleabag inn");
}
var x = paragraph.split(" ");
var repl= [Math.floor (Math.random()* 2)]
if(repl === 0 || repl === 1)
paragraph.replace(".", ". arrrr")
else
paragraph.replace(".", ".")
var readySentance=[];
while(x.indexOf(".")!==-1)
{
for(var i = 0; i < paragraph.length; ++i)
{
x.push(". Arrrr");
}
}
and my HTML looks like this
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title> Pirate Translator</title>
<!--<link rel = "stylesheet" href="css/normalize.css" />
<link rel = "stylesheet" href="css/styles.css" />-->
</head>
<body>
<h1> Land Lovin' Lady's Pirate Translator</h1>
<p> Simply click on the buttons to translate words and/or phrases from English to pirate talk</p><hr />
<form name = "pirateForm">
<div>
<textarea id="input"></textarea>
<textarea id="out" readonly></textarea>
<input onclick= "changed();" type="button" id ="translate" value="translate"/>
<input onclick="clearArea2()" type="button" id="clear2" value= "clear"/>
<script src="pirate4.js"></script><br>
</form>
</div>
</body>
</html>
Use a regular expression (so that you can specify the g global flag) and a callback in the replace:
paragraph = paragraph.replace(/\./g, function(){ return Math.random() < 0.5 ? ". arrrr" : "." });
As that is replacing all occurances with one command, you won't get stuck in a loop that will put an arrrr after every period no matter how many tries it has to do to get through the randomness.
In the same way you can use a regular expression in all your replacements, so that you don't need to have them in a loop. This will replace all occurances of hello:
paragraph = paragraph.replace(/hello/g, "Ahoy");

highlighting only the First string in Search

I am new to JavaScript. I am facing a problem with my javascript code. I am trying to use the string replace method to highlight the searched text.
But My function only highlight the First string that it find and dont highlight another strings !!
How can I fix it to find all strings that I type in search .
Here is my Code :
<html>
<head>
<script language="javascript">
function search()
{
var s = document.getElementById("p1").innerHTML
document.getElementById("p1").innerHTML = s.replace(document.getElementById('txt').value , '<span style="color:red">'+document.getElementById("txt").value+'</span>')
}
</script>
</head>
<body>
<input type="text" id="txt" value="search..." onfocus="value=''" />
<input type="button" id="btn" value="search" onclick="search()"/>
<p id="p1">
Type any word from this paragraph in the box above, then click the "Search" button to highlight it red
</p>
</body>
Regular expression with g global flag will help:
function search() {
var p1 = document.getElementById("p1"),
value = document.getElementById("txt").value,
regex = new RegExp("\\b" + value + "\\b", "gi"),
rwith = '<span style="color: red;">$&</span>';
p1.innerHTML = p1.innerHTML.replace(regex, rwith);
}
DEMO: http://jsfiddle.net/guC4j/
One option is to use split and join like so:
document.getElementById("p1").innerHTML = s.split(document.getElementById('txt').value).join('<span style="color:red">'+document.getElementById("txt").value+'</span>');
Here's a jsFiddle to play with.

Validation, javascript

I have this code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>sss</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type='text/javascript'>
function isAlphabet(obj){
var alphaExp = /[^a-z0-9_-]+/;
if(!obj.value.match(alphaExp)){
return true;
}
else{
alert('the bad symbols');
obj.focus();
return false;
}
}
</script>
</head>
<body>
<form action="/">
<input type='text' id='letters' onblur="isAlphabet(this)"/>
</form>
</body>
</html>
And I want to show an Alert() displaying only those characters for which validation fails.
For example :
If an input contains symbols like " #abc " , the Alert Message should show only "#". How can this be done?
Here's a simple way to do it... it's not be the most efficient though:
function isAlphabet(obj)
{
var val = obj.value;
var alphaExp = /[^a-z0-9_-]+/;
var valid = true;
var badchars = "";
for( a = 0; a < val.length; a++ )
{
if(val[a].match(alphaExp))
{
badchars += "," + val[a];
valid = false;
}
}
if( !valid )
{
alert("The following characters are not allowed: " + badchars.substr(1));
obj.focus();
}
return valid;
}
Use a regular expression which matches the allowed characters to get a string where those are removed. If the string contains anything, the validation fails:
function isAlphabet(obj) {
var alphaExp = /[a-z0-9_-]+/g;
var illegal = obj.value.replace(alphaExp, '');
if (illegal.length){
alert('Input contains the characters '+illegal+' which are not allowed.');
obj.focus();
return false;
} else {
return true;
}
}
In this case, you are matching characters that do not fall into the supplied ranges. Therefore, you can put the matched text into a backreference and use that.
Alternatively, you can construct a Regexp object and use it's lastMatch property.
You could matchall on regex which contains all the prohibited symbols (like your alphaExp), and then concatenate the matches.
if you use the g modifier, you can get .match() to return you an array of matches (invalid chars in your case) then you can just display them.
see "String.match(pattern)" about 1/3 down this page: http://evolt.org/regexp_in_javascript
var str = "Watch out for the rock!".match(/r?or?/g)
str then contains ["o","or","ro"]

Categories