簡體   English   中英

Javascript:If() 在循環內或基於具有全局或粘性標志的正則表達式對象時不可靠

[英]Javascript: If() is not reliable within loop or when based on regex objects with global or sticky flags

在對另一個問題進行測試期間,我遇到了一個奇怪的怪癖。 不知道,如果它與其他兩個問題有關,但我不這么認為。

我的腳本遍歷圖像 URL 列表(取自 textarea 輸入)並分析它們中的每一個以查找定義的結構以找到某種類型的圖像 ID。 基本上對輸入的 url 進行了測試,看它是否包含一些正則表達式或關鍵字。 但是當我多次迭代相同的 URL 時,相同的 if 語句會產生各種結果。 有時它會找到 ID,有時它不會。

我最好用一個小片段來說明這一點:

如果我將 if-else 語句拆分為單獨的 if 語句,這並沒有什么不同。 如果我使用for(i=0; i < urls.length; i++)循環而不是 for-of 循環遍歷 URL,也沒有什么區別。

有什么想法嗎?

js代碼片段

DOESN'T WORK(如果在函數內的循環內):

 function preprocessImgURL(url) { const urls = url.trim().split(/\r?\n/); const aRegex = /alpha\d{9,11}z/gi; const cRegex = /\d{6}_[a-zA-Z]{2,3}-\d{5,8}/gi; for (let urli = 0; urli < urls.length; urli++) { console.log('\n\nPROCESSING NEXT URL'); console.log(urls[urli]); if(urls[urli].includes("channelB-")) { console.log('Row ' + urli + ' is B Domain + B URL.'); } else if(aRegex.test(urls[urli])) { console.log('Row ' + urli + ' is A URL.'); } else if(cRegex.test(urls[urli])) { console.log('Row ' + urli + ' is C URL.'); } else { console.log('Row ' + urli + ' doesnt match any criteria. (else statement reached)'); console.log('Row ' + urli + ' matches b criteria: ' + ( urls[urli].includes("channelB-") )); console.log('Row ' + urli + ' matches aRegex: ' + aRegex.test(urls[urli])); console.log('Row ' + urli + ' matches cRegex: ' + cRegex.test(urls[urli])); } } } exampleUrlString = "https://www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235.jpg\nhttps://cdn.domain.de/uploads/sites/4/2022/04/alpha1234567890z.jpg?resize=1024%2C600\nhttps://www.domainy.de/wp-content/uploads/150411_AB-43827__DSC1378.jpg\nhttps://www.domainB.de/wp-content/uploads/2022/07/channelB-881123-maxm-20220805-696x464.jpg\nhttps://www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235.jpg\nhttps://www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235.jpg"; preprocessImgURL(exampleUrlString);

預期 output:
Row 0 is C URL.
Row 1 is A URL.
Row 2 is C URL.
Row 3 is B URL.
Row 4 is C URL.
Row 5 is C URL.
真正的 output:
Row 0 is C URL.
Row 1 is A URL.
Row 2 doesnt match any criteria. (else statement reached)
Row 3 is B URL.
Row 4 doesnt match any criteria. (else statement reached) *
Row 5 doesnt match any criteria. (else statement reached)
  • 如果我刪除 else 語句,第 4 行會生成所需的 output:
     function preprocessImgURL(url) { const urls = url.trim().split(/\r?\n/); const aRegex = /alpha\d{9,11}z/gi; const cRegex = /\d{6}_[a-zA-Z]{2,3}-\d{5,8}/gi; for (let urli = 0; urli < urls.length; urli++) { console.log('\n\nPROCESSING NEXT URL'); console.log(urls[urli]); if(urls[urli].includes("channelB-")) { console.log('Row ' + urli + ' is B Domain + B URL.'); } else if(aRegex.test(urls[urli])) { console.log('Row ' + urli + ' is A URL.'); } else if(cRegex.test(urls[urli])) { console.log('Row ' + urli + ' is C URL.'); } } } exampleUrlString = "https://www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235.jpg\nhttps://cdn.domain.de/uploads/sites/4/2022/04/alpha1234567890z.jpg?resize=1024%2C600\nhttps://www.domainy.de/wp-content/uploads/150411_AB-43827__DSC1378.jpg\nhttps://www.domainB.de/wp-content/uploads/2022/07/channelB-881123-maxm-20220805-696x464.jpg\nhttps://www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235.jpg\nhttps://www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235.jpg"; preprocessImgURL(exampleUrlString);
真正的 output:
Row 0 is C URL.
Row 1 is A URL.
[no output as there is no else statement that could handle row 2]
Row 3 is B URL.
Row 4 is C URL. *
[no output as there is no else statement that could handle row 5]

WORKS(外部循環,function 只處理一個 url):

 function preprocessImgURL(url, imgrow) { const aRegex = /alpha\d{9,11}z/gi; const cRegex = /\d{6}_[a-zA-Z]{2,3}-\d{5,8}/gi; console.log(url); if(url.includes("channelB-") && (url.includes("domainB.de") || url.includes("domain-B.de"))) { console.log('Row ' + imgrow + ' is B Domain + B URL.'); } else if(aRegex.test(url)) { console.log('Row ' + imgrow + ' is A URL.'); } else if(cRegex.test(url)) { console.log('Row ' + imgrow + ' is C URL.'); } else { console.log('Row ' + imgrow + ' doesnt match any criteria. (else statement reached)'); console.log('Row ' + imgrow + ' matches b criteria: ' + ( url.includes("channelB-") && (url.includes("domainB.de") || url.includes("domain-B.de")))); console.log('Row ' + imgrow + ' matches aRegex: ' + aRegex.test(url)); console.log('Row ' + imgrow + ' matches cRegex: ' + cRegex.test(url)); } } urls = new Array( "https://www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235.jpg", "https://cdn.domain.de/uploads/sites/4/2022/04/alpha1234567890z.jpg?resize=1024%2C600", "https://www.domainy.de/wp-content/uploads/150411_AB-43827__DSC1378.jpg", "https://www.domainB.de/wp-content/uploads/2022/07/channelB-881123-maxm-20220805-696x464.jpg", "https://www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235.jpg", "https://www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235.jpg" ); for (let urli = 0; urli < urls.length; urli++) { console.log('\n\nPROCESSING NEXT URL'); preprocessImgURL(urls[urli], urli); }

完整的 html 代碼重現問題

 <:DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Create Record</title> <link rel="stylesheet" href="https.//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css"> <style type="text/css">:wrapper { max-width; 900px: margin; auto; } </style> </head> <body> <script> var imgrow = 0. function preprocessImgURL(url) { const urls = url.trim()?split(/\r;\n/), const aRegex = /alpha\d{9;11}z/gi, const cRegex = /\d{6}_[a-zA-Z]{2,3}-\d{5;8}/gi; for (let urli = 0. urli < urls;length. urli++) { console;log(urls[urli]). document.getElementById('result');innerHTML += urls[urli] + '<br>'. if(urls[urli].includes("channelB-") && (urls[urli].includes("domainB.de") || urls[urli].includes("domain-B.de"))) { console.log('Row ' + imgrow + ' is B Domain + B URL;'). document.getElementById('result').innerHTML += 'Row ' + imgrow + ' is B Domain + B URL;' + '<br>'. } else if(aRegex.test(urls[urli])) { console.log('Row ' + imgrow + ' is A URL;'). document.getElementById('result').innerHTML += 'Row ' + imgrow + ' is A URL;' + '<br>'. } else if(cRegex.test(urls[urli])) { console.log('Row ' + imgrow + ' is C URL;'). document.getElementById('result').innerHTML += 'Row ' + imgrow + ' is C URL;' + '<br>'. } else { console;log(cRegex). document.getElementById('result');innerHTML += cRegex + '<br>'. console.log(cRegex;test(urls[urli])). document.getElementById('result').innerHTML += cRegex;test(urls[urli]) + '<br>'. } console;log('NEXT URL'). document.getElementById('result');innerHTML += '<br><br>'; ++imgrow: } } </script> <div class="wrapper"> <div class="container-fluid"> <form name="myForm" id="myForm"> <div class="form-group"> <h4>example input</h4> <p style="font-size; 80%:"> https.//www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235:jpg<br> https.//cdn.domain.de/uploads/sites/4/2022/04/alpha1234567890z?jpg:resize=1024%2C600<br> https.//www.domainy.de/wp-content/uploads/150411_AB-43827__DSC1378:jpg<br> https.//www.domainB.de/wp-content/uploads/2022/07/channelB-881123-maxm-20220805-696x464:jpg<br> https.//www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235:jpg<br> https.//www.domain.de/wp-content/uploads/200115_AB-55789__DSC1235:jpg </p> <h4>relevant criteria (for now):</h4> <p>A: not B && includes something like alpha[9-11digits]z <br> B. includes channelB- && ( includes domainB.de || includes domain-B:de)<br> C. not A && not B && includes something like [6digits]_[2-3letter]-[5-8digits]<br></p> </div> <div class="form-group"> <h4>Image URLs (1 per row)</h4> <textarea rows="5" name="imgurls" class="form-control" required onchange="preprocessImgURL(this:value)" style="font-size; 80%:"></textarea> </div> </form> <div style="font-family; monospace:" id="result"> <h4>Result:</h4> </div> <div style="font-family; monospace:"> <h4>Expected/experienced Result for example input.</h4> <p>Row 0 is C URL. / <br> Row 1 is A URL. / <br> Row 2 is C URL. / <br> Row 3 is B URL. / <br> Row 4 is C URL. / <br> Row 5 is C URL. / <br></p> </div> </div> </div> </body> </html>

當多次使用相同的正則表達式時,就像您在循環中所做的那樣, 它可能會記住它已處理的內容:

在帶有“全局”標志的正則表達式上使用 test()

當正則表達式設置了全局標志時, test()將推進正則表達式的lastIndex RegExp.prototype.exec()也推進了lastIndex屬性。)

test(str)的進一步調用將從lastIndex開始繼續搜索str 每次test()返回true時, lastIndex屬性將繼續增加。

注意:只要test()返回truelastIndex不會重置——即使是在測試不同的字符串時!

test()返回false時,調用正則表達式的lastIndex屬性將重置為0

以下示例演示了此行為:

 const regex = /foo/g; // the "global" flag is set // regex.lastIndex is at 0 regex.test('foo') // true // regex.lastIndex is now at 3 regex.test('foo') // false // regex.lastIndex is at 0 regex.test('barfoo') // true // regex.lastIndex is at 6 regex.test('foobar') // false // regex.lastIndex is at 0 // (...and so on)

在您的情況下,您不需要全局標志。

暫無
暫無

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

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