有很多匹配文件名有擴展名和路徑的例子。但是,我發現我的變化似乎更復雜。它是關於node.js require()
語句中的模塊名稱,其中擴展名是可選的,因此它可能存在或不存在。正則表達式匹配路徑和文件名,擴展名可選,沒有換行符,忽略註釋
我其實已經很遠了,如果這一點太複雜了,我可以輕鬆地生活我所擁有的。然而,好奇心促使我問社區。花了大部分時間在這些嘗試後,我真的想知道它是如何完成的!
注意當然,我可以很容易地解決正則表達式之外的問題,之後刪除任何可能存在的文件擴展名。我現在只是好奇可以做以內的正則表達式。
我試了幾個小時,嘗試使用預見性表達式的嘗試失敗了許多,我想我沒有完全理解它們(以前從未使用它們)。我甚至沒有開始嘗試檢測評論的聲明,如果任何人有一個解決方案,這種特殊情況下,它只是一個獎金,但
我試圖匹配路徑+文件名,我不'無法控制。他們甚至可能會被縮小,所以我沒有依靠線索的結束,或者它會很容易。
請參閱下面的演示代碼。這個示例測試文件故意看起來有點亂,我嘗試着將所有我能想到的奇怪的組合放在一起,並且我的正則表達式不得不處理。
可運行示例之前一些可選的背景下進一步下跌:
有一件事是專門爲我的具體情況,但是這部分解決了,見下圖:我不嘗試匹配任何路徑,但只有三種情況:./
,../lib/
和「」(無)。這是因爲這是關於動態模塊加載,並且模塊是node.js(無前綴,只允許一些),核心庫(../lib/
)的一部分或註定要在運行時從某處動態加載(./
- 該路徑指示這樣的模塊的代碼嘗試加載另一個這樣的模塊)。我將文件系統路徑保存在那裏,以便在開發過程中像Flow和IDE這樣的代碼檢查器有機會找到這些模塊,但是在運行時至少第三種模塊不在文件系統中。
這就是爲什麼在導入存儲過程中,我嘗試解析它們的require語句:爲了保持它們的CommonJS(node.js)同步性質,在實際加載請求的動態模塊之前,我加載所有依賴關係(遞歸地)。爲此,我需要通過解析它來收集每個模塊「require() - s」的內容。我只是說,作爲可選的信息片段,對於上下文,我無法控制這一點,所以我不知道如何(在)是可取的(爲什麼爲什麼仍然失蹤從我的描述)。該系統將更改,只是不是現在。
下面是可運行的測試情況下,最好我本來的名字沒有可選的擴展,和兩個註釋掉的比賽中刪除:
const testText: string = `
/**
* There are 8 active require() statements in here and 2 commented-out ones.
*/
const fs = require('fs'); require("../lib/store.js"); let t = require("crypto");
//OtherStuff: type defs comments etc.
let iah = require("./imap-account-handler.js"); //let iah = require("./inactive");
//let iah = require("./imap.js");
require("./imap-mailbox-handler");
const mX = require("./modX.js"); require("./modX.js"); require("./modY.js");
otherStuff();
otherStuff();
`;
const regex: RegExp = new RegExp(
// 1) Start indicator (account for allowed whitespace characters)
'require\\s*\\(\\s*["\']' +
// 2) match[1]: optional group for the prefix, which can only(!) be
// either "../lib" or "./"
'(' +
// 2.1) ...either a prefix indicating a core "One" module
// (captured by parent group)
'(?:\\.\\./lib/)' +
'|' +
// 2.2) ...or a prefix indicating a dynamic module
// (captured by parent group)
'(?:\\./)' +
')?' +
// 3) match[2]: Actual module name with or without file ending. We
// exclude the character that stands for the directory hierarchy
// and the two possible quote characters, everything else is
// allowed: This is not a check for name validity!
'([^/\\"\']+)' +
// 4) End indicator
'["\']\\s*\\)',
// 5) Flag "g" (global) There can be many "require(...)" commands.
'g'
);
let m: {[index: number]: string, index: number, input: string};
let count: number = 1;
while (m = regex.exec(testText)) {
console.log(
`${count++}: Prefix ${m[1] || '(none)'} ${'\t'} Name ${m[2] || '(none)'}`
);
}
好的答案,不僅是因爲解決了評論問題,而且還簡化了正則表達式(使用'regex = /.../而不是'new RegExp('...')'),因此提高了可讀性。我只是提出了兩點小小的改進:1)cleanComments正則表達式可能會覆蓋「空評論」的情況:'/\/\/.*/'而不是'/\/\/.+/'; 2)路徑捕獲部分'([^'「] +?)'可能改爲'([^'」。] +)':也不包括點,它避免了'+?'(非貪婪)量詞,因此消耗更少的正則表達式引擎的步驟。 – cFreed
我最初有'([^'「。+)'',但問題是它不適用於任何包含'.'的文件名(我將其中一個文件名更改爲'imap-account-h。 andler.js'來測試這個確切的場景)同樣對於評論來說,這是一個很好的總結,但在這種情況下,我們並不需要關心空的評論,因爲檢查的唯一理由是擺脫註釋-out需要語句 – jmcgriz
是的,這就是偉大的人,被標記爲答案,我故意將它寫成一個字符串,因爲這是將它分散到多行的唯一方法,這樣我就可以分別爲每個組件添加雙反斜槓我認爲,從現在開始半年,我想優化編輯該表達式的速度,而不是代碼的速度,因爲這是某些東西的一部分,只能很少運行,如果只運行一次,可以運行 –