国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

移除注釋的完善思路:真的可以用正則實(shí)現(xiàn)?

WalkerXu / 796人閱讀

摘要:導(dǎo)語網(wǎng)上有很多自稱能實(shí)現(xiàn)移除注釋的正則表達(dá)式,實(shí)際上存在種種缺陷。為了避免正則的記憶功能,都使用了正則字面量進(jìn)行測試。下面是去除單行注釋的最終代碼。修改方式將刪除注釋的正則改為。無法正確的移除引號塊。

導(dǎo)語

網(wǎng)上有很多自稱能實(shí)現(xiàn)移除JS注釋的正則表達(dá)式,實(shí)際上存在種種缺陷。這使人多少有些愕然,也不禁疑惑到:真的可以用正則實(shí)現(xiàn)嗎?而本篇文章以使用正則移除JS注釋為目標(biāo),通過實(shí)踐,由淺及深,遇到問題解決問題,一步步看看到底能否用正則實(shí)現(xiàn)!

移除注釋的完善思路:真的可以用正則實(shí)現(xiàn)? 1 單行注釋

單行注釋要么占據(jù)一整行,要么處于某一行的最后。
正常情況下不難,直接通過正則匹配,再用replace方法移除便可。

let codes = `
  let name = "Wmaker"; // This is name.
  if (name) {
    // Print name.
    console.log("His name is:", name);
  }
`;

console.log( codes.replace(///.*$/mg, "") );

// 打印出:
// let name = "Wmaker"; 
// if (name) {
//   
//   console.log("His name is:", name);
// }

上面是成功的刪除了注釋,不過對于獨(dú)占一整行的注釋清理的不夠徹底,會留下空白行。實(shí)際上,行尾注釋前面的空白也被保留了下來。所以目標(biāo)稍稍提高,清除這些空白。操作起來也并不難,思路大致這樣:刪除整行,實(shí)際上是刪除本行末尾的換行符或上一行末尾的換行符。而換行符本身也屬于空白符。所以只需操作正則,匹配到注釋以及注釋前面所有的空白符即可,一箭雙雕。

let codes = `
  let name = "Wmaker"; // This is name.
  if (name) {
    // Print name.
    console.log("His name is:", name);
  }
`;

console.log( codes.replace(/s*//.*$/mg, "") );

// 打印出:
// let name = "Wmaker";
// if (name) {
//   console.log("His name is:", name);
// }

如果在字符串中出現(xiàn)完整的URL地址,上面的正則會直接匹配而將其刪除。網(wǎng)上大多會將URL的格式特征(http://xxx):雙下劃線前面有冒號,作為解決途徑加以利用。但這只是治標(biāo)不治本的做法,畢竟//以任何形式出現(xiàn)在字符串中是它的自由,我們無從干涉。

這樣問題就轉(zhuǎn)變成:如何使正則匹配存在于引號外的雙下劃線?
想匹配被引號包圍,帶有雙下劃線的代碼塊比較簡單:/".*//.*"/mg。難點(diǎn)在于如何實(shí)現(xiàn)這個否定,即當(dāng)正則匹配到雙下劃線后,再判斷其是否在引號里面?絞盡腦汁,也上網(wǎng)查了很多,都沒有像樣的結(jié)果。靜心平氣,洗把臉?biāo)⑺⒀涝贈_個頭冷靜之后,覺得單純使用正則的路已經(jīng)走不通了,得跳出這個圈。

就在近乎精盡人亡的最后關(guān)頭,在那淫穢污濁的房間上方突然光芒萬丈。我急忙護(hù)住了充滿血絲的眼睛,靜待其適應(yīng)后定睛一看。只見那里顯現(xiàn)出了一段文字(Chinese):孩兒啊,先將帶有//被引號包圍的字符串替換掉,去掉注釋后再還原,不就行了嗎?

let codes = `
  let name = "Wmaker"; // This is name.
  if (name) {
    // Print name.
    console.log("His name is:", name);
    console.log("Unusual situation, characters of // in quotation marks.");
  }
`;

// 之前的方式。
console.log( codes.replace(/s*//.*$/mg, "") );
// 打印出:
// let name = "Wmaker";
// if (name) {
//   console.log("His name is:", name);
//   console.log("Unusual situation, characters of
// }

// 現(xiàn)在的方式。
console.log( removeComments(codes) );
// 打印出:
// let name = "Wmaker";
// if (name) {
//   console.log("His name is:", name);
//   console.log("Unusual situation, characters of // in quotation marks.");
// }

function removeComments(codes) {
  let {replacedCodes, matchedObj} = replaceQuotationMarksWithForwardSlash(codes);

  replacedCodes = replacedCodes.replace(/s*//.*$/mg, "");
  Object.keys(matchedObj).forEach(k => {
    replacedCodes = replacedCodes.replace(k, matchedObj[k]);
  });

  return replacedCodes;

  function replaceQuotationMarksWithForwardSlash(codes) {
    let matchedObj = {};
    let replacedCodes = "";
    
    let regQuotation = /".*//.*"/mg;
    let uniqueStr = "QUOTATIONMARKS" + Math.floor(Math.random()*10000);

    let index = 0;
    replacedCodes = codes.replace(regQuotation, function(match) {
      let s = uniqueStr + (index++);
      matchedObj[s] = match;
      return s;
    });

    return { replacedCodes, matchedObj };
  }
}

是的,目標(biāo)達(dá)成了,老天眷顧啊!
另外,有一個需要優(yōu)化的地方:定義字符串的方式有三種 " " ` ,目前我們只匹配了雙引號。

為了避免正則的記憶功能,都使用了正則字面量進(jìn)行測試。

--- 之前
console.log( /".*//.*"/mg.test(`"Unu//sual"`) ); // false
console.log( /".*//.*"/mg.test(`"Unu//sual"`) ); // true
console.log( /".*//.*"/mg.test(``Unu//sual``) ); // false

--- 之后
console.log( /("|"|`).*//.*1/mg.test(`"Unu//sual"`) ); // true
console.log( /("|"|`).*//.*1/mg.test(`"Unu//sual"`) ); // true
console.log( /("|"|`).*//.*1/mg.test(``Unu//sual``) ); // true

啊!問題到此結(jié)束了!
真的結(jié)束了嗎?不!我看了看時間:02:17,然后將眼鏡摘下,扯了張紙巾,拭去了幾顆淚水。

以下是接連解決的兩個問題:貪婪模式和轉(zhuǎn)義字符。

--- STEP 1,由于正則的貪婪模式導(dǎo)致。
let codes = `
  let str = "abc//abc"; // abc"
`;
console.log( codes.match(/("|"|`).*//.*1/mg) ); // [""abc//abc"; // abc""]

-- 解決

let codes = `
  let str = "abc//abc"; // abc"
`;
console.log( codes.match(/("|"|`).*?//.*?1/mg) ); // [""abc//abc""]


--- STEP 2,由定義字符串時其中的轉(zhuǎn)義字符導(dǎo)致。
let codes = `
  let str = "http://x"x.com"; // "acs
`;
console.log( codes.match(/("|"|`).*?//.*?1/mg) ); // [""http://x"", ""; // ""]

-- 解決

let reg = /(?

事情到這里,雖然勞累,但多少有些成就感,畢竟成功了。

可是,可是,可是在測試時,竟然無意間發(fā)現(xiàn)一個無法逾越的障礙。就好比費(fèi)勁千辛萬苦花費(fèi)無盡的財力物力之后,某某尤物終于愿意一同去情人旅館時,卻發(fā)現(xiàn)家家爆滿,沒有空余的房間。在強(qiáng)裝歡笑,玩命的哄騙著她,一家接連一家的尋找直到終于定到房間后,卻發(fā)現(xiàn)自己已然挺不起來了!

正則會將任意位置的引號作為查找的起始位置,它不在乎引號是成雙的道理。下面是一個示例。

let reg = /(?

不過,問題好歹在補(bǔ)過覺之后的 06:37 時得以解決。
思路是這樣的:雖然不能正確實(shí)現(xiàn)匹配帶有//被引號包圍的代碼塊(可能有方法,但能力有限),但是簡化成匹配單純被引號包圍的代碼塊,是簡單而且能正確做到的,雖然耗費(fèi)的內(nèi)存多了一些。另外,兩引號間也可能包含換行符,所以為其增加s模式:.代表全部字符。下面是去除單行注釋的最終代碼。

let codes = `
  let name = "Wmaker"; // This is name.
  let str = "http://x"x.com" + " / / " + "/"/"/"; // "; // " "
  if (name) {
    // Print name.
    console.log("His name is:", name);
    console.log("Unusual situation, characters of // in quotation marks.");
  }
`;

console.log(removeComments(codes));
// 打印出:
// let name = "Wmaker";
// let str = "http://x"x.com" + " / / " + "/"/"/";
// if (name) {
//   console.log("His name is:", name);
//   console.log("Unusual situation, characters of // in quotation marks.");
// }


function removeComments(codes) {
  let {replacedCodes, matchedObj} = replaceQuotationMarksWithForwardSlash(codes);

  replacedCodes = replacedCodes.replace(/s*//.*$/mg, "");
  Object.keys(matchedObj).forEach(k => {
    replacedCodes = replacedCodes.replace(k, matchedObj[k]);
  });

  return replacedCodes;

  function replaceQuotationMarksWithForwardSlash(codes) {
    let matchedObj = {};
    let replacedCodes = "";
    
    let regQuotation = /(?

最后補(bǔ)充一點(diǎn),單雙引號雖然也可以多行顯示,但其解析后實(shí)際是單行的。

let codes = "" 
  Wmaker 
"";
codes.match( /(?
2 多行注釋

啊!難點(diǎn)已經(jīng)解決,現(xiàn)在就可以悠哉悠哉的往前推進(jìn)了。
多行注釋與單行思路相同,只需在刪除注釋時多加一個匹配模式。中和兩者的最終代碼如下。

let codes = `
  let name = "Wmaker"; // This is name.
  let str = "http://x"x.com" + " / / " + "/"/"/"; // "; // " "
  let str = "http://x"x./*a*/com" + " / / " + "/"/"/"; // "; // "/*sad*/ "
  if (name) {
    // Print name.
    /* Print name. */
    console.log("His name is:", name);
    console.log("Unusual situation, characters of // in quotation marks.");
    /*
     * Others test.
     */
    console.log("Unusual situation, characters of /* abc */ in quotation marks.");
  }
`;

console.log(removeComments(codes));
// 打印出:
// let name = "Wmaker";
// let str = "http://x"x.com" + " / / " + "/"/"/";
// let str = "http://x"x./*a*/com" + " / / " + "/"/"/";
// if (name) {
//   console.log("His name is:", name);
//   console.log("Unusual situation, characters of // in quotation marks.");
//   console.log("Unusual situation, characters of /* abc */ in quotation marks.");
// }

function removeComments(codes) {
  let {replacedCodes, matchedObj} = replaceQuotationMarksWithForwardSlash(codes);

  replacedCodes = replacedCodes.replace(/(s*//.*$)|(s*/*[sS]*?*/)/mg, "");
  Object.keys(matchedObj).forEach(k => {
    replacedCodes = replacedCodes.replace(k, matchedObj[k]);
  });

  return replacedCodes;

  function replaceQuotationMarksWithForwardSlash(codes) {
    let matchedObj = {};
    let replacedCodes = "";
    
    let regQuotation = /(?
3 總結(jié)

從以上可以得出結(jié)論,單純使用正則表達(dá)式是不能達(dá)到目標(biāo)的,需要配合其它操作才行。但現(xiàn)在得出的結(jié)果真的能覆蓋全部的情況?會不會有其它的隱藏問題,比如多字節(jié)字符的問題。雖然作為一個碼農(nóng),該有的自信不會少,但慢慢的也明白了自己的局限性。從網(wǎng)上的其它資料看,使用UglifyJS,或在正確的解析中去除注釋,會更為穩(wěn)妥。但有可能自己動手解決的,沒理由不花費(fèi)些精力試試!

問題更新記錄
已發(fā)現(xiàn),暫時不能用此思路解決問題。
感謝熱心同志找出的錯誤,我會將能改與不能改的都列于此地,并只會更新下面兩個示例的代碼。

1.沒有考慮正則字面量中的轉(zhuǎn)義字符。
出錯示例:var reg=/a//;
修改方式:將刪除注釋的正則改為:/(s*(?

2.無法替換正則字面量。
出錯示例:var a=/abc/*123;var b=123*/123/。雖然的確是沒意義的代碼,但一無語法錯誤,二能被引擎解析。
修改方式:無,以之前的思維暫時沒辦法。
原因:無法像簡單替換引號一樣,先行替換正則字面量。

3.無法正確的移除引號塊。
出錯示例:

let codes = `
  let name = "Wmaker"; // direct`ive of f" write as f".
  let name = "Wmaker"; // direct`ive of f" write as f".
  let name = `
    /* name */
  `;
`;

修改方式:無,以之前的思維暫時沒辦法。
原因:""的情況比較好解決,但是`即可單行也可多行。

這里是工作于前端頁面的代碼及相應(yīng)示例,下載鏈接。





  
  Remove Comments



  

輸入:



輸出:

這里是工作于Node端的代碼及相應(yīng)示例,下載鏈接。運(yùn)行命令:node 執(zhí)行文件 待轉(zhuǎn)譯文件 轉(zhuǎn)移后文件

const fs = require("fs");
const path = require("path");
const process = require("process");


let sourceFile = process.argv[2];
let targetFile = process.argv[3];
if (!sourceFile || !targetFile) {
  throw new Error("Please set source file and target file.");
}

sourceFile = path.resolve(__dirname, sourceFile);
targetFile = path.resolve(__dirname, targetFile);

fs.readFile(sourceFile, "utf8", (err, data) => {
  if (err) throw err;
  fs.writeFile(targetFile, removeComments(data), "utf8", (err, data) => {
    if (err) throw err;
    console.log("Remove Comments Done!");
  });
});

function removeComments(codes) {
  let {replacedCodes, matchedObj} = replaceQuotationMarksWithForwardSlash(codes);

  replacedCodes = replacedCodes.replace(/(s*(? {
    replacedCodes = replacedCodes.replace(k, matchedObj[k]);
  });

  return replacedCodes;

  function replaceQuotationMarksWithForwardSlash(codes) {
    let matchedObj = {};
    let replacedCodes = "";
    
    let regQuotation = /(?
延伸閱讀

ES6精華:字符串?dāng)U展。文章鏈接。
ES6精華:正則表達(dá)式擴(kuò)展。文章鏈接。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/96056.html

相關(guān)文章

  • H5學(xué)習(xí)

    摘要:為此決定自研一個富文本編輯器。本文,主要介紹如何實(shí)現(xiàn)富文本編輯器,和解決一些不同瀏覽器和設(shè)備之間的。 對ES6Generator函數(shù)的理解 Generator 函數(shù)是 ES6 提供的一種異步編程解決方案,語法行為與傳統(tǒng)函數(shù)完全不同。 JavaScript 設(shè)計模式 ② 巧用工廠模式和創(chuàng)建者模式 我為什么把他們兩個放在一起講?我覺得這兩個設(shè)計模式有相似之處,有時候會一個設(shè)計模式不能滿...

    aristark 評論0 收藏0
  • Javascript正則匹配不含某子串

    摘要:在中就體現(xiàn)成用正則表達(dá)式進(jìn)行文件名匹配。字符串匹配恩,那么不包括呢顯然,這就需要用到正則的位置匹配了和都是不正確的,匹配前面不是的的位置。參考正則表達(dá)式分鐘入門教程正則表達(dá)式匹配不包含某個字符串通俗易懂還有圖 問題重現(xiàn) 不知道各位旁友在webpack的使用中,有沒有碰到下面的問題情景: 在使用了css Module的情況下,同時又希望用一些global的布局,其實(shí)在css Module...

    huaixiaoz 評論0 收藏0
  • 前端開發(fā)知識點(diǎn)整理

    摘要:前言本文主要是有關(guān)前端方面知識按照目前的認(rèn)知進(jìn)行的收集歸類概括和整理,涵蓋前端理論與前端實(shí)踐兩方面。 前言:本文主要是有關(guān)前端方面知識按照 XX 目前的認(rèn)知進(jìn)行的收集、歸類、概括和整理,涵蓋『前端理論』與『前端實(shí)踐』兩方面。本文會告訴你前端需要了解的知識大致有什么,看上去有很多,但具體你要學(xué)什么,還是要 follow your heart & follow your BOSS。 初衷...

    Blackjun 評論0 收藏0
  • 前端開發(fā)知識點(diǎn)整理

    摘要:前言本文主要是有關(guān)前端方面知識按照目前的認(rèn)知進(jìn)行的收集歸類概括和整理,涵蓋前端理論與前端實(shí)踐兩方面。 前言:本文主要是有關(guān)前端方面知識按照 XX 目前的認(rèn)知進(jìn)行的收集、歸類、概括和整理,涵蓋『前端理論』與『前端實(shí)踐』兩方面。本文會告訴你前端需要了解的知識大致有什么,看上去有很多,但具體你要學(xué)什么,還是要 follow your heart & follow your BOSS。 初衷...

    Sike 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<