網站搜尋

javascript - RegExp 在讀取的 HTML 文件上無法工作


首先,我知道大多數正則表達式問題都是怎麼樣的;而這不是那種「請幫我寫程式碼」的問題。

我感到困惑的地方在於,我的 RegExp 在 regexr 上有效,在 Chrome 的開發者工具中輪詢 document.body.textContent 時也有效,但在我用 io.js 讀取 HTML 文件後卻無效。

io.js 是版本 1.5.1,運行於 Windows 8

為什麼它在列出的兩個地方都可以運作,但在 io.js 中卻不行?難道我沒有考慮到 io.js 在讀取文件時會做的某些事情嗎?

我的 RegExp 應該像下面的連結那樣匹配 "@{each ___->___} text and line breaks @{/each}",但它卻返回 null

這是我試圖使用的: http://regexr.com/3aldk

正規表示式:

/@\{each ([a-zA-Z0-9->.]*)\}([\s\S]*)@\{\/each}/g

JS(範例):

fs.readFile('view.html', {encoding:'utf8'}, function(error, html) {
    console.log(html.match(myRegExp)); // null
});

HTML:

<!doctype html>
<html>
    <head>
        <title>@{title}</title>
    </head>
    <body>
        <h1>@{foo.bar}</h1>
        <p>
            Lorem ipsum dolor sit amet, @{foo.baz.hoo}
        </p>
        @{each people->person}
            <div>
                <b>@{person.name}:</b> @{person.age}
            </div>
        @{/each}
    </body>
</html>

我是不是漏掉了什麼明顯的東西,比如一個只存在於背面、但從未被使用過的角色?

答案#1

這裡的問題在於 規格 與 實作 之間的微妙界線。

ECMAscript 5.1 規範指出:

一個 - 字元可以被當作字面使用,或者它可以表示範圍。如果它是 ClassRanges 的第一個或最後一個字元、範圍規格的起始或終止限制,或者緊跟在範圍規格之後,它就會被當作字面使用。

Regular-Expressions.info 指出:

在字符類中,位於其他位置的連字號如果無法形成範圍,可能會被解釋為字面值或錯誤。不同的正則表達式版本對此非常不一致。

結論:

在字元類別中包含破折號 - 減號的 安全 方法是透過以下任一方式:

  • 轉譯它(例如 [a-zA-Z0-9\->.])
  • 將它放在字元類別的第一個字元(例如 [-.>a-zA-Z0-9])

    • 例外:在否定字元類別中它排在第二位,就在 ^ 之後(例如 [^-.>a-zA-Z0-9])
  • 將它放在類別的最後(例如 [a-zA-Z0-9.>-])

一般程式碼編寫指南建議先放置範圍,並以連字號結尾字元類別,這可以避免歧義並有助於可讀性。

總結來說,你的正則表達式應該變成:

/@\{each ([a-zA-Z0-9>.-]*)\}([\s\S]*)@\{\/each}/g

作為額外的提示:

你也可以把 [\s\S](任何空白字元或任何非空白字元)重寫成 [^](不是沒有)

這將導致你得到以下的正則表達式:

/@\{each ([a-zA-Z0-9>.-]*)\}([^]*)@\{\/each}/g

JavaScript ... 將 [^] 視為一個否定的空字符類,匹配任何單一字符。 - 來源