Leviscus Tempris Leviscus Tempris - 6 months ago 13
jQuery Question

Using RegExp in JQuery .replace() to pull file & line info from string?

I am working on my own JQuery/JavaScript console.log and have the following code, as a test working on Chrome, :

console.log(new Error().stack.replace(/\n/g, ''));


It produces the following:

Error at http://www.mywebsite.com/sites/all/themes/mythemedir/js/page.js:353:15 at b.event.dispatch (http://www.mywebsite.com/sites/all/modules/jquery_update/replace/jquery/1.9/jquery.min.js?v=1.9.1:3:28337) at b.event.add.v.handle (http://www.mywebsite.com/sites/all/modules/jquery_update/replace/jquery/1.9/jquery.min.js?v=1.9.1:3:25042)


I want to change
/\n/g
into whats needed to get each of the following results:

var errorPath = "http://www.mywebsite.com/sites/all/themes/mythemedir/js/";
var errorFile = "page.js";
var errorLoc = "353:15";
var errorLineNum = "353";
var errorColNum = "15";


For example, I have:

var errorFull = new Error().stack;
var errorPath = errorFull.replace(/(https?\:\/\/[^ ]*)/i, '');
var errorFile = errorFull.replace(/([^\\]+)\.js$/gi, '');
var errorLoc = errorFull.replace(/\n/g, '');
var errorLineNum = errorFull.replace(/\n/g, '');
var errorColNum = errorFull.replace(/\n/g, '');


Any ideas? I've read and have tested what I could from http://www.w3schools.com/jsref/jsref_obj_regexp.asp & https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp with varying results.
var errorFile
seems to crash and are the closest I've gotten to figuring it out from examples. Still haven't figured out a way to grab the text at the end of the first path on either and both sides of the colon (:).

Updates:

01.
var errorPath
is working, returning full match at the moment.

var errorPath = errorFull.replace(/(https?\:\/\/[^ ]*)/i, '');


Returns:
"http://www.mywebsite.com/sites/all/themes/mythemedir/js/page.js:353:15"


02.
var errorPath
is working, returning only path:

var errorPath = errorFull.replace(/(https?\:\/\/[^ ]*)(?:\/)/i, '');


Returns:
"http://www.mywebsite.com/sites/all/themes/mythemedir/js/"








Final Solution:



Finally figured it out with the understanding gained from the answers and help below! Thank you to @winner_joiner & @Tomalak for all of the resources and guidance! The final solution is as follows:

var errorData = /((?:https?\:\/\/[^\s]+)(?:\/))([^:]+).([^\D]+).([^\D]+)/i.exec((new Error()).stack);
var errorPath = errorData[1];
var errorFile = errorData[2];
var errorLoc = errorData[3] + ":" + errorData[4];
var errorLineNum = errorData[3];
var errorColNum = errorData[4];
console.log("errorPath: "+errorPath+", errorFile: "+errorFile+", errorLoc: "+errorLoc+", errorLineNum: "+errorLineNum+", errorColNum: "+errorColNum);


RegExr example in action global & non-global

The expression is broken up into 4 capturing groups:
errorPath
(Path),
errorFile
(File Name),
errorLineNum
(Line Number) and
errorColNum
(Column Number). The entire expression is not run globally, since the only URL in the error that references the location of the error is the first one, we only need to match the first set. So all that we are focusing on is:

http://www.mywebsite.com/sites/all/themes/mythemedir/js/page.js:353:15


errorPath (
errorData[1]
) (Path):
((?:https?\:\/\/[^\s]+)(?:\/))


This portion selects everything from
http://
or
https://
up to and including the last
/
resulting in:
http://www.mywebsite.com/sites/all/themes/mythemedir/js/
.

The
s?
in
https?
makes the
s
portion optional.

errorFile (
errorData[2]
) (File Name):
([^:]+)


This portion selects everything since the Path and the next (in this case also first)
:
resulting in:
page.js
.

errorLineNum (
errorData[3]
) (Line Number):
.([^\D]+)


This portion skips any separating symbol (This case:
:
) & selects everything until the next non-digit (
\D
), resulting in:
353
.

errorColNum (
errorData[4]
) (Column Number):
.([^\D]+)


This portion skips any separating symbol (This case:
:
) & selects everything until the next non-digit (
\D
) again, resulting in:
15
.

Demonstration can be found at RegExr.

Answer

This could be a quick solution, where you get the whole data with one expression

var errorData = /\s*at\s*(.*\/)([^\/:]+):([^:]+):([^:]+)\n/gi.exec((new Error()).stack);
var errorPath = errorData[1];
var errorFile = errorData[2];
var errorLoc = errorData[3] + ":" + errorData[4];
var errorLineNum = errorData[3];
var errorColNum = errorData[4];
// tested on Win7 with chrome 44+ 

Just an Hint: if you use the g modifier in a regex an call the function moretimes very time it gets the next find. detail to this you can find here Why RegExp with global flag in Javascript give wrong results?

Update 1:

\s*at\s* gets the first line with spaces and at and spaces

(.*\/) gets the url until to the last slash /

([^\/:]+) gets the file name

:([^:]+) gets the colon and anything until to the next colon

:([^:]+)\n gets anything from the colon until to the newline

Comments