簡體   English   中英

Javascript 多正則表達式模式

[英]Javascript multiple regex pattern

我試圖從查看站點中的某些徽標和鏈接中排除某些內部 IP 地址和某些內部 IP 地址格式。我有多個 IP 地址范圍(示例如下)。 是否可以使用javascript編寫一個可以匹配下面列表中所有IP地址的正則表達式?

10.X.X.X
12.122.X.X
12.211.X.X
64.X.X.X
64.23.X.X
74.23.211.92
and 10 more

引用句號,用\\d+替換 X,然后用管道將它們連接在一起:

const allowedIPpatterns = [ 
  "10.X.X.X", 
  "12.122.X.X",
  "12.211.X.X",
  "64.X.X.X",
  "64.23.X.X",
  "74.23.211.92"   //, etc.
];

const allowedRegexStr = '^(?:' + 
  allowedIPpatterns.
    join('|').
    replace(/\./g, '\\.').
    replace(/X/g, '\\d+') + 
  ')$';

 const allowedRegexp = new RegExp(allowedRegexStr);

然后你就准備好了:

 '10.1.2.3'.match(allowedRegexp) // => ['10.1.2.3']
 '100.1.2.3'.match(allowedRegexp) // => null

這個怎么運作:

首先,我們必須將單個 IP 模式轉換為與其意圖匹配的正則表達式。 “'12.122.X.X' 形式的所有 IP”的一個正則表達式是這樣的:

^12\\.122\\.\\d+\\.\\d+$

  • ^表示匹配必須從字符串的開頭開始; 否則,112.122.XX IP 也會匹配。
  • 12等:數字匹配自己
  • \\. : 正則表達式中的句點完全匹配任何字符; 我們想要文字句點,所以我們在前面放了一個反斜杠。
  • \\d : [0-9]簡寫; 匹配任何數字。
  • + :表示“1 或更多” - 1 或更多數字,在這種情況下。
  • $ :類似於^ ,這意味着匹配必須在字符串的末尾結束。

因此,我們將 IP 模式轉換為這樣的正則表達式。 對於單個模式,您可以使用如下代碼:

const regexStr = `^` + ipXpattern. 
  replace(/\./g, '\\.').
  replace(/X/g, '\\d+') + 
  `$`;

這只是替換了所有. s 與\\. X s 與\\d+並將^$粘在末端。

(注意加倍的反斜杠;字符串解析和正則表達式解析都使用反斜杠,所以無論我們想要一個文字的哪個地方使它通過字符串解析器到正則表達式解析器,我們都必須將它加倍。)

在正則表達式中,替換this|that匹配任何匹配thisthat 因此,如果我們將列表轉換為re1|re2|re3|...|relast形式的單個正則表達式,我們可以立即檢查與所有 IP 的匹配re1|re2|re3|...|relast

然后我們可以進行一些重構,使正則表達式匹配器的工作更容易; 在這種情況下,由於所有的正則表達式都會有^...$ ,我們可以將這些約束從單個正則表達式中移出並將它們放在整個事物上: ^(10\\.\\d+\\.\\d+\\.\\d+|12\\.122\\.\\d+\\.\\d+|...)$ 括號使^不只是第一個模式的一部分,而$不只是最后一個模式的一部分。 但是由於普通括號捕獲以及分組,並且我們不需要捕獲任何內容,我將它們替換為非分組版本(?: .. )

在這種情況下,我們可以在巨大的字符串上進行一次全局搜索和替換,而不是在每個模式上單獨進行。 所以結果就是上面的代碼:

const allowedRegexStr = '^(?:' + 
  allowedIPpatterns.
    join('|').
    replace(/\./g, '\\.').
    replace(/X/g, '\\d+') + 
  ')$';

那仍然只是一個字符串; 我們必須把它變成一個實際的RegExp對象來進行匹配:

const allowedRegexp = new RegExp(allowedRegexStr);

正如所寫,這不會過濾掉非法 IP - 例如, 10.1234.5678.9012將匹配第一個模式。 如果要將單個字節值限制為十進制范圍 0-255,則可以使用比\\d+更復雜的正則表達式,如下所示:

(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])

匹配“任何一位或兩位數字,或 '1' 后跟任意兩位數字,或 '2' 后跟 '0' 到 '4' 中的任何一個,然后是任何數字,或 '25' 后跟任何 '0'通過'5'”。 用它替換\\d將完整的字符串處理表達式變成這樣:

const allowedRegexStr = '^(?:' + 
  allowedIPpatterns.
    join('|').
    replace(/\./g, '\\.').
    replace(/X/g, '(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])') + 
  ')$';

並使實際的正則表達式看起來更加笨拙:

^(?:10\.(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])\.(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5]).(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])|12\.122\....

但你不必看它,只需與它匹配即可。 :)

你可以用正則表達式來做,但它不會很漂亮,特別是因為 JavaScript 甚至不支持冗長的正則表達式,這意味着它必須是一個沒有任何注釋的龐大的正則表達式行。 此外,正則表達式不適合匹配數字范圍。 我懷疑有更好的工具來處理這個問題。

好吧,這里是(對於您提供的樣本):

var myregexp = /\b(?:74\.23\.211\.92|(?:12\.(?:122|211)|64\.23)\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])|(?:10|64)\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]))\b/g;

作為詳細(“可讀”)正則表達式:

\b                 # start of number
(?:                # Either match...
 74\.23\.211\.92   # an explicit address
|                  # or
 (?:               # an address that starts with
  12\.(?:122|211)  # 12.122 or 12.211
 |                 # or
  64\.23           # 64.23
 )
 \.                # . 
 (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.  # followed by 0..255 and a dot
 (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])    # followed by 0..255
|                  # or
 (?:10|64)         # match 10 or 64
 \.                # . 
 (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.  # followed by 0..255 and a dot
 (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.  # followed by 0..255 and a dot
 (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])    # followed by 0..255
)
\b                 # end of number

/^(X|\\d{1,3})(\\.(X|\\d{1,3})){3}$/應該這樣做。

如果您實際上不需要匹配“X”字符,則可以使用:

\b(?:\d{1,3}\.){3}\d{1,3}\b

否則我會使用 cebarrett 提供的解決方案。

我不完全確定您要在這里實現什么(看起來其他人也不是)。

但是,如果是驗證,那么這里有一個解決方案來驗證不使用 RegEx 的 IP 地址。 首先,在點處分割輸入字符串。 然后在數字上使用 parseInt,確保它不高於 255。

function ipValidator(ipAddress) {
var ipSegments = ipAddress.split('.');
for(var i=0;i<ipSegments.length;i++)
    {
        if(parseInt(ipSegments[i]) > 255){
            return 'fail';
        }
    }
return 'match';
}

運行以下返回“匹配”:

document.write(ipValidator('10.255.255.125'));

而這將返回“失敗”:

document.write(ipValidator('10.255.256.125'));

這是 jsfiddle 中的一個注釋版本,其中包含一些示例, http://jsfiddle.net/VGp2p/2/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM