在 JS .replace() 中使用 RegEx 从字符串中提取文件和行信息?

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

我正在自己工作 JavaScript console.log 并且有以下代码,作为在 Chrome 上工作的测试,:

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

它产生以下内容:

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)

我想将 /\n/g 更改为获得以下每个结果所需的内容:

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";

比如我有:

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, '');

有什么想法吗?我已经阅读并测试了 http://www.w3schools.com/jsref/jsref_obj_regexp.asp & https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp 中的内容,但结果各不相同。 var errorFile 似乎崩溃了,这是我从示例中得出的最接近结果。仍然没有想出一种方法来抓取第一个路径末尾的冒号 (:) 两侧的文本。

更新:

01. var errorPath 正在工作,目前正在返回完整匹配。

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

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

02. var errorPath 正在工作,仅返回路径:

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

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



最终解决方案:

经过下面的解答和帮助,终于搞明白了!感谢@winner_joiner 和@Tomalak 提供的所有资源和指导!最终解决方案如下:

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);

表达式分为 4 个捕获组:errorPath(路径)、errorFile(文件名)、errorLineNum(行号)和 errorColNum(列号)。整个表达式并不是全局的运行,因为error中唯一引用错误位置的URL是第一个,我们只需要匹配第一个集合即可。所以我们关注的是:

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

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

这部分选择从 http://https:// 到并包括最后一个 / 的所有内容,结果为:http://www.mywebsite.com/sites/all/themes/mythemedir/js/

https? 中的 s? 使 s 部分可选。

errorFile (errorData[2]) (文件名): ([^:]+)

这部分选择了 Path 和下一个(在本例中也是第一个): 之后的所有内容,结果是:page.js.

errorLineNum (errorData[3]) (行号): .([^\D]+)

这部分跳过任何分隔符号(本例::)并选择所有内容,直到下一个非数字(\D),导致:353.

errorColNum (errorData[4]) (列号): .([^\D]+)

这部分跳过任何分隔符号(本例::)并再次选择下一个非数字(\D)之前的所有内容,结果为:15.

可在 RegExr 找到演示。

这可能是一个快速的解决方案,您可以通过一个表达式获取全部数据

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?

更新 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