regex.test VS string.match เพื่อทราบว่าสตริงตรงกับนิพจน์ทั่วไปหรือไม่


287

หลายครั้งที่ฉันใช้matchฟังก์ชันสตริงเพื่อทราบว่าสตริงตรงกับนิพจน์ทั่วไปหรือไม่

if(str.match(/{regex}/))

มีความแตกต่างระหว่างสิ่งนี้หรือไม่:

if (/{regex}/.test(str))

พวกเขาดูเหมือนจะให้ผลลัพธ์เดียวกัน


4
นี่คือการทดสอบที่ดีที่สุดที่คุณจะได้พบกับjsperf.com/regexp-test-vs-match-m5
ajax333221

@ ajax333221 ขอบคุณ jsperf แต่ฉันไม่แน่ใจว่ามันดี การจับคู่ regex ใช้กลุ่มการจับคู่ซึ่งไม่จำเป็นเมื่อค้นหาค่าบูลีน
gdoron ให้การสนับสนุนโมนิก้า

คำตอบ:


440

การใช้งานพื้นฐาน

ก่อนอื่นเรามาดูกันว่าแต่ละฟังก์ชั่นทำอะไร:

regexObject ทดสอบ ( สตริง )

ดำเนินการค้นหาการจับคู่ระหว่างการแสดงออกปกติและสตริงที่ระบุ ผลตอบแทนจริงหรือเท็จ

เชือก จับคู่ ( RegExp )

ใช้เพื่อดึงข้อมูลการแข่งขันเมื่อจับคู่สตริงกับนิพจน์ทั่วไป ส่งกลับอาร์เรย์ด้วยการจับคู่หรือnullถ้าไม่มี

เนื่องจากnullประเมินfalse,

if ( string.match(regex) ) {
  // There was a match.
} else {
  // No match.
} 

ประสิทธิภาพ

มีความแตกต่างเกี่ยวกับประสิทธิภาพหรือไม่

ใช่แล้ว ฉันพบบันทึกย่อนี้ในเว็บไซต์ MDN :

หากคุณต้องการทราบว่าสตริงตรงกับนิพจน์ปกติ regexp หรือไม่ให้ใช้ regexp.test (สตริง)

ความแตกต่างสำคัญหรือไม่

คำตอบอีกครั้งคือใช่ ! jsPerfนี้ที่ฉันรวบรวมไว้แสดงความแตกต่างคือ ~ 30% - ~ 60%ขึ้นอยู่กับเบราว์เซอร์:

ทดสอบการแข่งขัน  การทดสอบประสิทธิภาพ

ข้อสรุป

ใช้.testถ้าคุณต้องการการตรวจสอบบูลีนที่เร็วขึ้น ใช้.matchเพื่อดึงข้อมูลการแข่งขันทั้งหมดเมื่อใช้gค่าสถานะโกลบอล


5
ไม่แปลกใจนักเนื่องจากฟังก์ชั่นสตริงจำเป็นต้องพลิกสิ่งต่างๆแล้วสร้างอาเรย์ถ้ามีคู่ที่ตรงกัน ดูเหมือนว่าฉันจะใช้.test()ต่อไป :)

22
สองเซนต์ของฉัน: ประสิทธิภาพการทำงานเกินจริง ตัวเลือกอย่างใดอย่างหนึ่งสามารถดำเนินการ ~ 15,000 ในการกะพริบของจอภาพดังนั้นถ้าคุณกำลังทำด้านลูกค้า regex จำนวนมากความเร็วไม่เกี่ยวข้อง แน่นอน 'ทดสอบ' เป็นฟังก์ชันที่ถูกต้องตามหลักเหตุผลหากผลลัพธ์บูลีนคือสิ่งที่คุณต้องการ ขอบคุณสำหรับ Q / A BTW
David Gilbertson

2
การทดสอบที่น่าสนใจนั้นช้ากว่าการแข่งขัน 41% สำหรับฉันโดยใช้การทดสอบ jsPerf ด้านบน (Chrome 41, OSX)
Benjie

1
@AlexShilman indexOf เร็วกว่า (แต่ไม่มาก) กว่าการทดสอบตามstackoverflow.com/questions/183496/นี้(คุณคาดว่าจะเร็วกว่านี้)
podperson

1
สิ่งหนึ่งที่อาจกัดคุณที่นี่ (ทำให้ทีมของฉันกัดเร็ว ๆ นี้): หากคุณใช้การตั้งค่าสถานะ 'g' บน Regex ของคุณและสร้างอินสแตนซ์ใหม่ (เช่นผ่าน RegExp ใหม่ (<regex_str>, 'g')) และนำมาใช้ซ้ำ ตัวอย่างเช่นการรัน "test" เป็น stateful กล่าวคือจะให้ผลลัพธ์ที่แตกต่างเมื่อทำงานหลายครั้ง ดูdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/…สำหรับรายละเอียด
davertron

118

อย่าลืมพิจารณาธงโลกใน regexp ของคุณ:

var reg = /abc/g;
!!'abcdefghi'.match(reg); // => true
!!'abcdefghi'.match(reg); // => true
reg.test('abcdefghi');    // => true
reg.test('abcdefghi');    // => false <=

นี่เป็นเพราะ Regexp ติดตาม lastIndex เมื่อพบการแข่งขันใหม่


21
ฉันเพิ่งจะตีหัวเมื่อเห็นว่า regex.test () ของฉันกำลังสุ่มเข้าสู่ระบบ "จริง" จากนั้น "เท็จ" จากนั้น "จริง" ... ขอบคุณ!
adriendenat

7
ฉันคิดว่านี่เป็นคำตอบที่ดีกว่า มันอธิบายว่าพวกเขาไม่ให้ผลลัพธ์เดียวกันและ reg.test () มีอันตรายที่เป็นอันตราย สำหรับฉันแล้วสิ่งนี้ทำให้ string.match () เป็นตัวเลือกที่ชัดเจน การแสดงไม่เคยเป็นปัญหาสำหรับฉันเลย
James

2
นี้เป็นสิ่งสำคัญ! บ้าไปแล้วลองคิดดูว่าทำไมผลลัพธ์อื่น ๆ ถึงขาดหายไป ... สำหรับการอ้างอิงของคนอื่นที่พบสิ่งนี้: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
Dan

2
หากคุณเป็นสับสนขณะที่ผมกำลังดูstackoverflow.com/q/1520800/3714913 นอกจากนี้ยังมีString.prototype.search ()ซึ่งส่งกลับดัชนี แต่ไม่มีปัญหานี้เท่าที่ฉันสามารถบอกได้
Nateowami

3
แค่อยากรู้อยากเห็นว่าการมีธงระดับโลกเป็น.test()อย่างไร ไม่ใช่จุดที่.test()จะตรวจสอบว่าสตริงมี regexp ตรงกันหรือไม่
buhbang

0

นี่คือผลลัพธ์มาตรฐานของฉัน ผลการเปรียบเทียบ

ทดสอบ 4,267,740 ops / วินาที± 1.32% (สุ่มตัวอย่าง 60 ครั้ง)

ผู้บริหาร 3,649,719 คน / วินาที± 2.51% (สุ่มตัวอย่าง 60 ครั้ง)

ตรงกับ 3,623,125 ops / วินาที± 1.85% (สุ่มตัวอย่างรัน 62 ครั้ง)

indexOf 6,230,325 ops / วินาที± 0.95% (สุ่มตัวอย่าง 62 ครั้ง)

วิธีการทดสอบนั้นเร็วกว่าวิธีการจับคู่ แต่วิธีที่เร็วที่สุดคือ indexOf


indexOf ไม่ทำงานกับ regexes จึงค่อนข้างไม่เกี่ยวข้อง
gdoron ให้การสนับสนุนโมนิก้า
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.