I have the following regex patterns that matches all the 'act' that ends with numbers within a list of URLs.
Regex pattern /\/ch(\d+)\/act(\d+)/gi
Javascript code
pageSrc[1] = "../ch01/index.html";
pageSrc[2] = "../ch01/act01/1.html";
pageSrc[3] = "../ch01/act01/2.html";
pageSrc[4] = "../ch01/act02/1.html";
pageSrc[5] = "../ch01/act02/2.html";
pageSrc[6] = "../ch01/actx/1.html";
var pattern = /\/ch(\d+)\/act(\d+)/gi;
for(var i=0; i<pageSrc.length; ++i){
var hasAct = pattern.test(pageSrc[i]);
console.log(hasAct);
}
The expected results and actual results
| String | Expected Result | Actual Result |
| pageSrc[1] | false | false |
| pageSrc[2] | true | true |
| pageSrc[3] | true | *FALSE |
| pageSrc[4] | true | true |
| pageSrc[5] | true | *FALSE |
| pageSrc[6] | false | false |
Am not sure why pageSrc[3] won't return true. I used the regEx tester on gskinner.com and it worked fine, here is the link http://gskinner.com/RegExr/?344ap
Can anyone help me take a look please? thanks in advance!
Remove the g flag. From the RegExp.test documentation:
As with exec (or in combination with it), test called multiple times on the same global regular expression instance will advance past the previous match.
You don't want a global search when reusing a pattern like this.
> var pageSrc = [];
> pageSrc[1] = "../ch01/index.html";
pageSrc[2] = "../ch01/act01/1.html";
pageSrc[3] = "../ch01/act01/2.html";
pageSrc[4] = "../ch01/act02/1.html";
pageSrc[5] = "../ch01/act02/2.html";
pageSrc[6] = "../ch01/actx/1.html";
var pattern = /\/ch(\d+)\/act(\d+)/i;
for(var i=0; i<pageSrc.length; ++i){
var hasAct = pattern.test(pageSrc[i]);
console.log(i, hasAct);
}
0 false
1 false
2 true
3 true
4 true
5 true
6 false
You are using /g. Remove that flag to make it work.
The g flag makes the regex start matching from pattern.lastIndex (the index where the previous match ended), until it fails, and then start at 0.
Related
This question already exists:
JavaScript - use eval to get value in code string
Closed 1 year ago.
I am trying to evaluate JavaScript code based on what a user enters into a code editor. I get their code as a single string, use babel to transform it and then split on newlines to get the code by line. I want to see if the current line evaluates to something and if so, print that out. I skip lines that do not evaluate to anything but the problem is if some writes code like the following:
1 | const x = 5;
2 | x
Ideally I would like to print something like:
1 |
2 | 5
The problem though is that I need line 1 to evaluate line two. If I just join the lines of code and evaluate that (something like: const x = 5;\nx;) it will result in 5;
However, if a line further down does not evaluate to anything, then it will also return 5 but that is not correct because const y = 3; does not evaluate to 5. So for example the following:
1 | const x = 5;
2 | x
3 | const y = 3;
concatenated (something like: const x = 5;\nx\nconst y = 3;): would result in:
1 | undefined
2 | 5
3 | 5 // PROBLEM: this should also be undefined.
I have tried this solution: Context-preserving eval but it does not answer my question. Moreover, The solution throws an error in the following line when I tried it out:
// 'void (__EVAL = ${__EVAL.toString()});' causes an error
var __EVAL = s => eval(`void (__EVAL = ${__EVAL.toString()}); ${s}`);
I want to evaluate the latest statement in a block of code, given I have the code written before that, but only return a result if the current line evaluates to something. So as one final example, the following code:
1 | const x = 5;
2 | x
3 | const y = 3;
4 |
5 | const add = (a, b) => {
6 | return a + b;
7 | };
8 |
9 | add(x, y);
should give:
1 |
2 | 5
3 |
4 |
5 |
6 |
7 |
8 |
9 | 8
I have this quite long string that contains multiple information. So I guess we can say that its a couple of fields concatenated together without any delimiters. I understand that to make this work, all of the lengths of the fields should always be fixed. However, two of the fields represent a name and an amount and no prefixes/suffixes were implemented to maintain a fixed length.
I was wondering how would I got about this problem? Here's a sample of the string and how they should be separated:
Sample #1
Actual Input:
48001MCAbastillas2200800046300017100518110555130000123
How it should be separated:
480 | 01 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 130000 | 123
Sample #2
Actual Input:
48004MCAbastillas22008000463000171005181105555000000123
How it should be separated:
480 | 04 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 5000000 | 123
In my example only the amount has changed but I'm expecting that the name will vary in length as well. Any suggestion will be much appreciated.
I'd probably use a regular expression for this.
String test = "48004MCAbastillas22008000463000171005181105555000000123";
Pattern pattern = Pattern.compile("^(\\d{3})(\\d{2})([A-Za-z]+)(\\d{16})(\\d{6})(\\d{6})(\\d+)(\\d{3})$");
Matcher matcher = pattern.matcher(test);
if (matcher.matches())
{
for (int i = 1; i <= matcher.groupCount(); ++i)
{
System.out.print(matcher.group(i) + " | ");
}
}
Sample output:
480 | 04 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 5000000
| 123 |
Note that the third and second to last groups do not have fixed lengths.
It's more difficult if the name can contain numbers. My approach would be to run this against the data that you have and print a list of anything that doesn't match (i.e. add an else clause). Perhaps then you can come up with a better strategy for handling these cases. For example, something like ([A-Za-z]+\w*[A-Za-z]+) might be an improvement, because that will at least allow numbers in the middle of the name.
Sometimes you just have to accept that when the data you're given is crap, you just have to do the best that you can and that might mean throwing some of it away.
We want the output
480 | 01 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 130000
| 123
where the fields 3 and 7 had no fixed length.
Suppose that we store the string in a string var:
String s="48001MCAbastillas2200800046300017100518110555130000123";
We can find the fields 1 & 2 easly:
System.out.println(s.substring(0, 3)); //has 3 digit
System.out.println(s.substring(3, 5)); //has 2 digit
//we can reduce s
s=s.substring(6); //remove char from 0 to 5 included
If you'll call System.out.println(s); you well see
CAbastillas2200800046300017100518110555130000123
Now we have the string... I can deduce that it is composed only by char. So we have to find the first occurrence of a number... We can use a cycle:
int index=-1;
for( int i=0; i<s.length(); i++ ) {
if( Character.isDigit(s.charAt(i))) {
index=i;
System.out.println("There is a number in the position "+ index);
break;
}
}
Now you can extract your name with:
System.out.println(s.substring(0, index));
and extract the other 3 fields (you can optimize this part...)
System.out.println(s.substring(0, 16));
s=s.substring(16);
System.out.println(s.substring(0, 6));
s=s.substring(6);
System.out.println(s.substring(0, 6));
s=s.substring(6);
Finally, you can divide the remaining s in two part with length s.length.3 and 3:
System.out.println(s.substring(0, s.length()-3));
System.out.println(s.substring( s.length()-3,s.length()));
Your output will be:
480
01
There is a number in the position 11
CAbastillas
2200800046300017
100518
110555
130000
123
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
How can I use a regular expression to parse a generic, complex URL?
I want to get informations form URL string including protocol, host name and path.
Parsing URLs with Regular Expressions
You can parse URL/URI with Regular Expressions.
Example advanced URL look like:
http://login:password#www.example.org:80/demo/example.cgi?lang=de&foo=bar&empty#position
RegExr for parse that advanced URL is something like:
([^ :]*):\/\/(?:([^:]*):([^#]*)#|)([^/:]{1,}):?(\d*)?(\/[^? ]*)\??((?:[^=&# ]*=?[^&# ]*&?)*)#?([^ ]*)?
Yep, it's so crazy. But, you are able to obtain following fields from it (groups):
#1 Protocol, #2 Login, #3 Password, #4 Host name, #5 Port, #6 Path, #7 Query, #8 Fragment
Let's say you have some URL and want to know only a host name:
var myURL = "http://www.example.org/demo/example.cgi?lang=de&foo=bar&empty";
function getHostname(theURL) {
var Expr = /([^ :]*):\/\/(?:([^:]*):([^#]*)#|)([^/:]{1,}):?(\d*)?(\/[^? ]*)\??((?:[^=&# ]*=?[^&# ]*&?)*)#?([^ ]*)?/g,
match = Expr.exec(theURL);
if(match && match[0]) {
return match[4]; // #4th group of RegExpr
}
}
var myHostname = getHostname(myURL);
console.log(myHostname);
I create aslo a nice table where you can find RegExpr for every entries (at group #1) of URL string:
| URL entry name | Example | Regular Expression |
| ----------------- | --------------------- | ------------------------------- |
| Protocol | http | ([^ :]*):\/\/ |
| Login | admin | \/\/([^:]*):[^#]*(?=#) |
| Password | 12345 | \/\/[^:]*:([^#]*)(?=#) |
| Host name | www.example.org | (?:#|\/\/)([^/:]{1,}) |
| Domain parts | www, example, org | (?:#|\/\/|\.)([^./:]*)(?=[./:]) |
| Port | 80 | :(\d*)\/[^/] |
| Path | /demo/example.cgi | \/\/([^/][^? ]*)\?? |
| File name | example.cgi | ([^?/]*(?!\/))\? |
| Query string | lang=de&foo=bar&empty | \?((?:[^=&# ]*=?[^&# ]*&?)*) |
| Fragment/position | position | #([^ ]*) |
Additionally, you can parse the query string using ([^=&# ]*)=?([^&# ]*)&? and iterating the matches:
var myQueryString = "lang=de&foo=bar&empty";
function parseQueryString(theQueryString) {
var Expr = /([^=&# ]*)=?([^&# ]*)&?/g,
QueryEntries = {},
match;
// If no match left it returns ["", undefinied, undefinied],
// ["", "", ""] or null - depends on JavaScript engine/web browser.
// There is litte trick: "" and null is like false, so only check for [""].
while((match = Expr.exec(theQueryString)) && match[0]) {
QueryEntries[match[1]] = match[2] || '';
}
return QueryEntries;
}
var myQueryEntries = parseQueryString(myQueryString);
console.log(myQueryEntries);
You can test your RegExpr easily on http://regexr.com/.
Don't use regex. Use an URL parser.
function parseURL(url) {
var a = document.createElement('a');
a.href = url;
return a;
}
var urlData = parseURL('https://username:password#sub.example.com:123/foo/bar?a=b#c');
console.log(urlData.protocol); // https:
console.log(urlData.username); // username
console.log(urlData.password); // password
console.log(urlData.host); // sub.example.com:123
console.log(urlData.hostname); // sub.example.com
console.log(urlData.port); // 123
console.log(urlData.pathname); // /foo/bar
console.log(urlData.search); // ?a=b
console.log(urlData.hash); // #c
console.log(urlData.origin); // https://sub.example.com:123
console.log(urlData.href); // https://username:password#sub.example.com:123/foo/bar?a=b#c
There is also the URL interface. Has less browser support, but semantically it may be better than a DOM element.
var urlData = new URL('https://username:password#sub.example.com:123/foo/bar?a=b#c');
console.log(urlData.protocol); // https:
console.log(urlData.username); // username
console.log(urlData.password); // password
console.log(urlData.host); // sub.example.com:123
console.log(urlData.hostname); // sub.example.com
console.log(urlData.port); // 123
console.log(urlData.pathname); // /foo/bar
console.log(urlData.search); // ?a=b
console.log(urlData.hash); // #c
console.log(urlData.origin); // https://sub.example.com:123
console.log(urlData.href); // https://username:password#sub.example.com:123/foo/bar?a=b#c
What does the +d in
function addMonths(d, n, keepTime) {
if (+d) {
mean?
The + operator returns the numeric representation of the object. So in your particular case, it would appear to be predicating the if on whether or not d is a non-zero number.
Reference here. And, as pointed out in comments, here.
Operator + is a unary operator which converts the value to a number. Below is a table with corresponding results of using this operator for different values.
+----------------------------+-----------+
| Value | + (Value) |
+----------------------------+-----------+
| 1 | 1 |
| '-1' | -1 |
| '3.14' | 3.14 |
| '3' | 3 |
| '0xAA' | 170 |
| true | 1 |
| false | 0 |
| null | 0 |
| 'Infinity' | Infinity |
| 'infinity' | NaN |
| '10a' | NaN |
| undefined | NaN |
| ['Apple'] | NaN |
| function(val){ return val }| NaN |
+----------------------------+-----------+
Operator + returns a value for objects which have implemented method valueOf.
let something = {
valueOf: function () {
return 25;
}
};
console.log(+something);
It is a unary "+" operator which yields a numeric expression. It would be the same as d*1, I believe.
As explained in other answers it converts the variable to a number. Specially useful when d can be either a number or a string that evaluates to a number.
Example (using the addMonths function in the question):
addMonths(34,1,true);
addMonths("34",1,true);
then the +d will evaluate to a number in all cases. Thus avoiding the need to check for the type and take different code paths depending on whether d is a number, a function or a string that can be converted to a number.
I am trying to write a regular expression which has to adhere the following rules:
Y120.001/100.232k
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
| | | | | | | | This k may be any letter, is not required
| | | | | | | Another number if there was a dot
| | | | | | A dot, not required
| | | | | A number with at least one digit, not required if a letter follows
| | | | Always a slash
| | | If there's a dot, digits can follow
| | A dot, not required
| A number, at least one digit
Always Y
These strings should work:
Y120.001/1k
Y1/h
Y2039/100
Y29/47.0
These should not work:
x203/493s (Not a Y at the start)
Y/39x (No number after the Y)
Y83839 (Second half missing)
Y78/29 (Last letter missing)
This is my early attempt, but it does not work in PHP:
/^\$*(\d)*(.*(\d))\/*(.*(\d))*.$
This pattern should work:
^Y\d+(\.\d*)?/(\d+(\.\d*)?[a-z]?|[a-z])$
Demonstration
In javascript
re=/^Y\d+(\.\d+)?\/([a-z]$|\d+(\.\d+)?[a-z]?$)/
"Y120.001/1k Y1/h Y2039/100 Y29/47.0".split(" ").map(function(s) { return re.test(s) })
> [true, true, true, true]
"x203/493s Y/39x Y83839 Y78/29".split(" ").map(function(s) { return re.test(s) })
> [false, false, false, true]
This does accept Y78/29 as the trailing letter is optional.
After several iterations to correct for commented shortcomings:
/^Y\d+(?:\.\d+)?\/(?:(?:\d+(?:\.\d+)?)[A-Za-z]?|[A-Za-z])$/
Demonstration
Old Answer:
Here is a fully specific version that works well.
/^Y\d+(?:\.\d+)?\/(\d+(?:\.\d+)?)?[A-Za-z]?$/
Edited for a follow-up test in jsfiddle
^Y\d+\.?\d*/((\d+\.?\d*)[a-zA-Z]?|(\d+\.?\d*)?[a-zA-Z])$
You can check the explanation of the regex from here.
If I understand the nuances of your specification
\bY\d+(?:\.\d*)?/(?:[A-Za-z]|(?:\d+(?:\.\d+)?[A-Za-z]?))\b
I understand your specification to include that if the first dot is present, the following number(s) is/are optional; but if the 2nd dot is present, there must be at least one following number. Others seem to have interpreted that part of your requirements differently.
this pattern should work Y[\d.]+\/[\d.]*[a-z]? Demo
What about the following one?
var r = /^Y\d+(\.\d+)?\/(\d+(\.\d+)?|(\d+(\.\d+)?)?[A-Za-z])$/;
console.log(true === r.test('Y120.001/1k')); // true
console.log(true === r.test('Y1/h')); // true
console.log(true === r.test('Y2039/100')); // true
console.log(true === r.test('Y29/47.0')); // true
console.log(false === r.test('x203/493s')); // true
console.log(false === r.test('Y/39x')); // true
console.log(false === r.test('Y83839')); // true
try this:
/Y\d+\.?\d*\/\d+\.?\d*\w?/