I have a string with times (formatted HH:MM) each on a new line. I want to create a JS function to check if there is any times that does not belong. It should simply return true or false.
Example correct string: var s = "5:45\n07:00\n13:00\n17:00";
5:45
07:00
13:00
17:00
Example incorrect string: var s = "5:45\n07:00\n55:00\n17:00";
5:45
07:00
55:00 // incorrect date here, should return false
17:00
My regex experience is little to none. Playing around on Scriptular I created this expression to detect times that do match:
/^[0-2]?[0-9]\:[0-5][0-9]$/m. This however is not sufficient.
So, how can I get this to work with a string s as indicated above?
function checkIfStringConforms(s)
{
var all_good = [some magic with regex here]
return all_good;
}
PS: I have Googled around and checked answers on SO. My regex skill is... eh.
Your regex is OK, but it would also match 29:00, so it needs some improvement. Then, it's always a bit more difficult to find non-matches than it is to find matches. You could try and remove all matches from the string and then see if it's empty (except for whitespace):
result = s.replace(/^(?:2[0-3]|[01]?[0-9]):[0-5][0-9]$/mg, "");
If result is empty after that, there were no illegal times in your string.
It can be done without the use of any regex. Just split on new-line and see if every date matches your format. For that we could use Array.every
function checkIfStringConforms(s) {
return s.split("\n").every(function(str){
var arr = str.split(":");
return (arr[0] < 24 && arr[0] > -1) && arr[1] < (60 && arr[1] > -1)
});
}
/(((2[^0-3]|[3-9].):..)|(..?:[^0-5].))(\n|$)/
Regexp returns true if your s var has at least one invalid time. Please, check it carefully before use – your question is quite broad and restrictions are not fully defined. Regex assumes that you have something like x:xx or xx:xx in each line (x is a digit) – I’m not sure this assumption covers all your data.
Related
This question already has an answer here:
Find all regex matches
(1 answer)
Closed last year.
Okay, so I have this string "nesˈo:tkʰo:x", and I want to get the index of all the zero-width positions that don't occur after any instance of the character ˈ (the IPA primary stress symbol). So in this case, those expected output would be 0, 1, 2, and 3 - the indices of the letters nes that occur before the one and only instance of ˈ, plus the ˈ itself.
I'm doing this with regex for reasons I'll get into in a bit. Regex101 confirms that /(?=.*?ˈ)/ should match all 4 of those zero-width positions with JS' regex flavor... but I can't actually get JS to return them.
A simple setup might look like this:
let teststring = "nesˈo:tkʰo:x";
let re = new RegExp("(?=.*?ˈ)", "g");
while (result = re.exec(teststring)) {
console.log("Match found at "+result.index);
}
...except that this loops forever. It seems to get stuck on the first match, which I understand has something to do with how RegExp.exec is supposed to auto-increment RegExp.lastIndex for global regexes, or something. But I also can't make the regex not global, or it won't return all the matches for strings like this where more than one match is expected.
Okay, so what if I manually increment RegExp.lastIndex to prevent it from looping?
let teststring = "nesˈo:tkʰo:x";
let re = new RegExp("(?=.*?ˈ)", "g");
while (result = re.exec(teststring)) {
if (result.index == re.lastIndex) {
re.lastIndex++;
} else {
console.log("Match found at "+result.index);
}
}
Now it... prints out nothing at all. Now, to be fair, if lastIndex starts at 0 by default, and the index of the first match is 0, I half expect that to be skipped over... but why isn't it at least giving me 1, 2 and 3 as matches?
Now, I can already hear the chorus of "you don't need regex for this, just do Array(teststring.indexOf("ˈ")).keys() or something to generate [0,1,2,3]". That may work for this specific example, but the actual use case is a parser function that's supposed to be a general solution for "for this input string, replace all instances of A with B, if condition C is true, unless condition D is true". Those conditions might be something like "if A is at the end of the string" or "if A is right next to another instance of A" or "if A is between 'n' and 't'". That kind of complicated string matching problem is why the parser creates and executes regexes on the fly and why regex is getting involved, and it does work for almost everything except this one annoying edge case, which I'd rather not have to refactor the entire mechanism of the parser to deal with if I don't have to.
Use String.prototype.matchAll() to get all the matches.
let teststring = "nesˈo:tkʰo:x";
let re = new RegExp("(?=.*?ˈ)", "g");
[...teststring.matchAll(re)].forEach(result =>
console.log("Match found at " + result.index)
)
.search() returns the index of a match. .exec() returns an array of the match. Note a look ahead (?=) isn't needed, a standard capture group () suffices.
const str =`nesˈo:tkʰo:x",`;
const rgx = /(.*?ˈ)/;
let first = str.search(rgx);
let last = rgx.exec(str)[0].length - 1;
console.log('Indices: '+first+' - '+(first + last)+' \nLength: '+(last+1));
I'm new to regex, and have been researching all night how to remove the first 2 zeros from a string like "08/08/2017" (without removing 0 in "2017")
The 5+ regex tutorials I've reviewed do not seem to cover what I need here.
The date could be any sysdate returned from the system. So the regex also needs to work for "12/12/2017"
Here is the best I have come up with:
let sysdate = "08/08/2017"
let todayminuszero = str.replace("0","");
let today = todayminus0.replace("0","");
It works, but obviously it's unprofessional.
From the tutorials, I'm pretty sure I can do something along the lines of this:
str.replace(/\d{2}//g,""),);
This pattern would avoid getting the 3rd zero in str.
Replacement String would have to indicate 8/8/
Not sure how to write this though.
For date manipulation I would use other functions(best date related) but, this should do it, for the case that you stated. If you need other formats or so, I would suggest removing the zeros in an different way, but It all depends on you UseCase.
let sysdate = "08/08/2017";
let todayminuszero = sysdate.replace(/0(?=\d\/)/gi,"");
console.info(todayminuszero);
(?= ... ) is called Lookahead and with this you can see what is there, without replacing it
in this case we are checking for a number and a slash. (?=\d\/)
here some more information, if you want to read about lookahead and more http://www.regular-expressions.info/lookaround.html
A good place to test regex expressions is https://regex101.com/
I always use this for more advance expressions, since it displays all matching groups and so, with a great explaination. Great resource/help, if you are learning or creating difficult Expressions.
Info: as mentioned by Rajesh, the i flag is not needed for this Expression, I just use it out of personal preference. This flag just sets the expression-match to case insensitive.
-- Out of Scope, but may be interesting --
A longer solution without regex could look like this:
let sysdate = "08/08/2017";
let todayminuszero = sysdate.split("/").map(x => parseInt(x)).join("/");
console.info(todayminuszero);
Backside, this solution has many moving parts, the split function to make an array(´"08/08/2017"´ to ´["08", "08", "2017"]´), the map function, with a lambda function => and the parseInt function, to make out of each string item a nice integer (like: "08" to 8, ... ) and at last the join function that creates the final string out of the newly created integer array.
you should use this
let sysdate = "08/08/2017"
let todayminuszero = sysdate.replace(/(^|\/)0/g,"$1");
console.log(todayminuszero);
function stripLeadingZerosDate(dateStr){
return dateStr.split('/').reduce(function(date, datePart){
return date += parseInt(datePart) + '/'
}, '').slice(0, -1);
}
console.log(stripLeadingZerosDate('01/02/2016'));
console.log(stripLeadingZerosDate('2016/02/01'));
look at here
function stripLeadingZerosDate(dateStr){
return dateStr.split('/').reduce(function(date, datePart){
return date += parseInt(datePart) + '/'
}, '').slice(0, -1);
}
console.log(stripLeadingZerosDate('01/02/2016'));// 1/2/2016
console.log(stripLeadingZerosDate('2016/02/01'));// "2016/2/1"
By first 2 zeros, I understand you mean zero before 8 in month and in date.
You can try something like this:
Idea
Create a regex that captures group of number representing date, month and year.
Use this regex to replace values.
Use a function to return processed value.
var sysdate = "08/08/2017"
var numRegex = /(\d)+/g;
var result = sysdate.replace(numRegex, function(match){
return parseInt(match)
});
console.log(result)
I'm trying to execute following code :
var pwd = "CURRENT DATE - 23 DAYS";
var Exp = /^([CURRENT]{7}[ ]{1}[DATE]{4}[ ]{1}[-]{1}[ ]{1}[\d]+[ ]{1}[DAYS]{4})$/i;
var Exp2 = /^([CURRENT]{7}[ ]{1}[DATE]{4}[ ]{1}[-]{1}[ ]{1}[\d]+[ ]{1}[MONTHS]{6})$/i;
if (pwd.match(Exp) || pwd.match(Exp2)) {
alert("SUCCESS");
} else {
alert("ERROR");
}
It works as expected... But though I have given first-word CURRENT and mentioned 7 characters, It accepts if I give the wrong word like CUUUENT instead of CURRENT. How can I resolve this issue?
The sub-expression [CURRENT]{7} is saying repeat any of the letters in the set [CURRENT] seven times. What I think you meant to intend was to match the string CURRENT. That would just be CURRENT.
Much of your regular expressions are specifying the same thing. /^CURRENT DATE - [0-9]+ (DAYS|MONTHS)$/ should match what you have well enough.
With [CURRENT]{7} you match every character from [], and 7 of them. If you want to match the whole word, use (CURRENT)
It'd be better with (CURRENT DATE - \d{1} DAYS)
Note that whn you writr the whole word, it matches kt exactly as it it written. But [THIS]{4} captures any combination of 4 letters between [] like ITHS or HHHT.
I have the following example url: #/reports/12/expense/11.
I need to get the id just after the reports -> 12. What I am asking here is the most suitable way to do this. I can search for reports in the url and get the content just after that ... but what if in some moment I decide to change the url, I will have to change my algorythm.
What do You think is the best way here. Some code examples will be also very helpfull.
It's hard to write code that is future-proof since it's hard to predict the crazy things we might do in the future!
However, if we assume that the id will always be the string of consecutive digits in the URL then you could simply look for that:
function getReportId(url) {
var match = url.match(/\d+/);
return (match) ? Number(match[0]) : null;
}
getReportId('#/reports/12/expense/11'); // => 12
getReportId('/some/new/url/report/12'); // => 12
You should use a regular expression to find the number inside the string. Passing the regular expression to the string's .match() method will return an array containing the matches based on the regular expression. In this case, the item of the returned array that you're interested in will be at the index of 1, assuming that the number will always be after reports/:
var text = "#/reports/12/expense/11";
var id = text.match(/reports\/(\d+)/);
alert(id[1]);
\d+ here means that you're looking for at least one number followed by zero to an infinite amount of numbers.
var text = "#/reports/12/expense/11";
var id = text.match("#/[a-zA-Z]*/([0-9]*)/[a-zA-Z]*/")
console.log(id[1])
Regex explanation:
#/ matches the characters #/ literally
[a-zA-Z]* - matches a word
/ matches the character / literally
1st Capturing group - ([0-9]*) - this matches a number.
[a-zA-Z]* - matches a word
/ matches the character / literally
Regular expressions can be tricky (add expensive). So usually if you can efficiently do the same thing without them you should. Looking at your URL format you would probably want to put at least a few constraints on it otherwise the problem will be very complex. For instance, you probably want to assume the value will always appear directly after the key so in your sample report=12 and expense=11, but report and expense could be switched (ex. expense/11/report/12) and you would get the same result.
I would just use string split:
var parts = url.split("/");
for(var i = 0; i < parts.length; i++) {
if(parts[i] === "report"){
this.reportValue = parts[i+1];
i+=2;
}
if(parts[i] === "expense"){
this.expenseValue = parts[i+1];
i+=2;
}
}
So this way your key/value parts can appear anywhere in the array
Note: you will also want to check that i+1 is in the range of the parts array. But that would just make this sample code ugly and it is pretty easy to add in. Depending on what values you are expecting (or not expecting) you might also want to check that values are numbers using isNaN
I have a solution for my question, but I'm trying to get better at regex especially in javascript. I just wanted to bring this to the community to see if I could write this in a better way.
So, I get a datetime string that comes from .net and I need to extract the date from it.
Currently what I have is:
var time = "2009-07-05T00:00:00.0000000-05:00".match(/(^\d{4}).(\d{2}).(\d{2})/i);
As I said, this works, but I was hoping to make it more direct to only grab the Year, month, day in the array. What I get with this is 4 results with the first being YYYY-MM-DD, YYYY, MM, DD.
Essentially I just want the 3 results returned, not so much that this doesn't work (because I can just ignore the first index in the array), but so that I can learn to use regex a bit better.
Anytime you have parenthesis in your regex, the value that matches those parenthesis will be returned as well.
time[0] is what matches the whole expression
time[1] is what matches ([\d]{4}), i.e. the year
time[2] is what matches the first ([\d]{2}), i.e. the month
time[3] is what matches the second ([\d]{2}), i.e. the date
You can't change this behavior to remove time[0], and you don't really want to (since the underlying code is already generating it, removing it wouldn't give any performance benefit).
If you don't care about getting back the value from a parenthesized expression, you can use (?:expression) to make it non-matching.
I don't think that you can do that but you can do
var myregexp = /(^\d{4})-(\d{2})-(\d{2})/g;
var match = myregexp.exec(subject);
while (match != null) {
for (var i = 1; i < match.length; i++) {
// matched text: match[i]
}
match = myregexp.exec(subject);
}
And then just loop from the index 1. The first item in the array is a match and then the groups are children of that match