javascript regex - ดูทางเลือกอื่นหรือไม่


143

นี่คือ regex ที่ทำงานได้ดีในการใช้งาน regex ส่วนใหญ่:

(?<!filename)\.js$

สิ่งนี้ตรงกับ. js สำหรับสตริงที่ลงท้ายด้วย. js ยกเว้น filename.js

Javascript ไม่มีการมอง regex ทุกคนสามารถรวบรวม regex ทางเลือกซึ่งได้ผลลัพธ์เหมือนกันและทำงานใน javascript หรือไม่

นี่คือความคิดบางอย่าง แต่ต้องการฟังก์ชั่นตัวช่วย ฉันหวังว่าจะบรรลุมันด้วย regex: http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript


3
หากคุณต้องการตรวจสอบชื่อไฟล์เฉพาะหรือรายการชื่อไฟล์ทำไมไม่ใช้เพียงสองเช็ค ตรวจสอบว่ามันลงท้ายด้วย. js แล้วถ้าเป็นเช่นนั้นตรวจสอบว่ามันไม่ตรงกับ filename.js หรือในทางกลับกัน
si28719e

3
ปรับปรุง: ล่าสุดสาธารณะ Chrome เวอร์ชัน (v62) รวมถึง (จากการทดลองสมมุติ) lookbehinds ออกจากกล่อง: D หมายเหตุ แต่ที่ lookbehinds ยังคงอยู่ในข้อเสนอขั้นตอนที่ 3: github.com/tc39/proposal-regexp-lookbehind ดังนั้นอาจใช้เวลาสักครู่จนกว่า JavaScript รองรับทุกที่ ควรระวังเกี่ยวกับการใช้ในการผลิต!
Eirik Birkeland

2
# อัปเดต: ES2018 รวมถึงการยืนยันคำ สั่ง lookbehind Plus : - โหมด dotAll (ธงของ s) - การยืนยันคำสั่ง Lookbehind - กลุ่มจับภาพที่มีชื่อ - การหลบหนีของคุณสมบัติ Unicode
Ashley Coolman

2
เพียงแค่ใช้(?<=thingy)thingyสำหรับlookbehind บวกและ(?<!thingy)thingyสำหรับlookbehind เชิงลบ ตอนนี้มันสนับสนุนพวกเขา
КонстантинВан

7
@ K._ ตั้งแต่ ก.พ. 2018 ยังไม่เป็นความจริง !! และจะต้องใช้เวลาพอสมควรเพราะเบราว์เซอร์และเอ็นจิ้นจะต้องติดตั้งสเปค (ปัจจุบันเป็นแบบร่าง)
Andre Figueiredo

คำตอบ:


64

^(?!filename).+\.js ทำงานได้สำหรับฉัน

ทดสอบกับ:

  • ตรงกับ test.js
  • การแข่งขัน blabla.js
  • filename.js ไม่ตรงกัน

คำอธิบายที่เหมาะสมสำหรับ regex นี้สามารถพบได้ที่นิพจน์ปกติเพื่อจับคู่สตริงที่ไม่มีคำ?

มองไปข้างหน้ามีให้ตั้งแต่javascript รุ่น 1.5และรองรับโดยเบราว์เซอร์หลักทั้งหมด

อัปเดตให้ตรงกับ filename2.js และ 2filename.js แต่ไม่ใช่ filename.js

(^(?!filename\.js$).).+\.js


5
คำถามที่คุณเชื่อมโยงกับการเจรจาเกี่ยวกับปัญหาที่แตกต่างกันเล็กน้อย: จับคู่สตริงที่ไม่ได้มีคำเป้าหมายได้ทุกที่ อันนี้ง่ายกว่ามาก: จับคู่สตริงที่ไม่ได้ขึ้นต้นด้วยคำเป้าหมาย
Alan Moore

นั่นเป็นสิ่งที่ดีจริงๆมันพลาดเฉพาะในกรณีเช่น: filename2.js หรือ filenameddk.js หรือคล้ายกัน นี่ไม่ใช่การแข่งขัน แต่ควรเป็นการแข่งขัน
daniel

9
@daniel คุณขอดูหลังไม่ใช่มองไปข้างหน้าทำไมคุณถึงยอมรับคำตอบนี้
hek2mgl

1
คนที่ได้รับไม่ตรงกับa.js
inetphantom

1
regex ดั้งเดิมที่มี lookbehind ไม่ตรงกัน2filename.jsแต่ regex ที่ให้ที่นี่ทำ อันที่เหมาะสมกว่าก็^(?!.*filename\.js$).*\.js$คือ วิธีนี้ตรงกับยกเว้น*.js *filename.js
weibeld

153

แก้ไข: จาก ECMAScript 2018 เป็นต้นไปยืนยัน lookbehind (แม้มากมาย) ได้รับการสนับสนุนโดยกำเนิด

ในเวอร์ชันก่อนหน้าคุณสามารถทำสิ่งนี้:

^(?:(?!filename\.js$).)*\.js$

นี่จะทำสิ่งที่นิพจน์ Lookbehind ดำเนินการอย่างชัดเจน: ตรวจสอบอักขระแต่ละตัวของสตริงถ้านิพจน์ lookbehind บวกกับ regex หลังจากนั้นจะไม่ตรงกันและอนุญาตให้อักขระนั้นตรงกันเท่านั้น

^                 # Start of string
(?:               # Try to match the following:
 (?!              # First assert that we can't match the following:
  filename\.js    # filename.js 
  $               # and end-of-string
 )                # End of negative lookahead
 .                # Match any character
)*                # Repeat as needed
\.js              # Match .js
$                 # End of string

การแก้ไขอื่น:

มันทำให้ฉันต้องพูด (โดยเฉพาะอย่างยิ่งเมื่อคำตอบนี้ได้รับการยกระดับขึ้นมาก) ว่ามีวิธีที่ง่ายกว่ามากในการบรรลุเป้าหมายนี้ ไม่จำเป็นต้องตรวจสอบ lookahead ในตัวละครทุกตัว:

^(?!.*filename\.js$).*\.js$

ทำงานได้ดีเช่นกัน:

^                 # Start of string
(?!               # Assert that we can't match the following:
 .*               # any string, 
  filename\.js    # followed by filename.js
  $               # and end-of-string
)                 # End of negative lookahead
.*                # Match any string
\.js              # Match .js
$                 # End of string

ทำงานในหลายกรณียกเว้นที่มีอักขระนำหน้าเช่น: filename.js (works-nomatch) filename2.js (จับคู่การทำงาน) blah.js (ทำงาน - จับคู่) 2filename.js (ไม่ทำงาน - ตั้งชื่อ) --- มีกล่าวว่า lookbehind มีข้อ จำกัด เหมือนกันซึ่งผมไม่ทราบจนถึงขณะนี้ ...
daniel

9
@ Daniel: ดี regex ของคุณ (กับ lookbehind) 2filename.jsยังไม่ตรงกับ regex ของฉันตรงกันในทุกกรณีเหมือนกับ regex ตัวอย่างของคุณ
ทิม Pietzcker

ให้อภัยความไร้เดียงสาของฉัน แต่มีประโยชน์สำหรับกลุ่มที่ไม่ถูกจับที่นี่หรือไม่? ฉันรู้อยู่เสมอว่าจะมีประโยชน์เมื่อพยายามรวบรวมข้อมูลอ้างอิงเพื่อแทนที่ในสตริง เท่าที่ฉันรู้สิ่งนี้ก็จะใช้ได้เช่นกัน ^ (?! ชื่อไฟล์ \ .js $). * \. js $
ฉันต้องการคำตอบ

1
ไม่มากนัก regex ตรวจสอบ "filename.js" เฉพาะตอนเริ่มต้นของสตริง แต่^(?!.*filename\.js$).*\.js$จะได้ผล พยายามนึกถึงสถานการณ์ที่กลุ่ม ncg อาจยังจำเป็น ...
Tim Pietzcker

วิธีการนี้สามารถสรุปได้ดังนี้: แทนที่จะมองไปที่ X มองไปข้างหน้ากับตัวละครทุกตัวที่มาก่อน X?
Sarsaparilla

25

สมมติว่าคุณต้องการค้นหาทั้งหมดที่intไม่ได้นำหน้าด้วยunsigned:

ด้วยการสนับสนุนการมองเชิงลบ:

(?<!unsigned )int

โดยไม่สนับสนุนการมองที่ไม่ดี:

((?!unsigned ).{9}|^.{0,8})int

แนวคิดพื้นฐานคือการคว้าตัวละครก่อนหน้าและไม่รวมการจับคู่กับการค้นหาเชิงลบ แต่ยังตรงกับกรณีที่ไม่มีตัวละคร n นำหน้า (โดยที่ n คือความยาวของการดูด้านหลัง)

ดังนั้น regex ในคำถาม:

(?<!filename)\.js$

จะแปลเป็น:

((?!filename).{8}|^.{0,7})\.js$

คุณอาจต้องเล่นกับกลุ่มจับเพื่อหาจุดที่แน่นอนของสตริงที่คุณสนใจหรือคุณไม่ต้องการแทนที่ส่วนที่เฉพาะเจาะจงด้วยอย่างอื่น


ฉันเพิ่งแปลงสิ่งนี้(?<!barna)(?<!ene)(?<!en)(?<!erne) (?:sin|vår)e?(?:$| (?!egen|egne))ให้(?!barna).(?!erne).(?!ene).(?!en).. (?:sin|vår)e?(?:$| (?!egen|egne))เป็นเคล็ดลับสำหรับความต้องการของฉัน เพียงให้สิ่งนี้เป็นอีกสถานการณ์ "จริง" ดูลิงค์
Eirik Birkeland

ฉันคิดว่าคุณหมายถึง:((?!unsigned ).{9}|^.{0,8})int
pansay

@pansay ใช่ ขอบคุณ. ฉันเพิ่งแก้ไขคำตอบของฉัน
Kamil Szot

2
ขอบคุณสำหรับคำตอบทั่วไปที่ทำงานได้ดียิ่งขึ้นแม้ในที่ที่มีความจำเป็นที่จะต้องตรงกับส่วนลึกของข้อความ
Milos Mrdovic

5

หากคุณสามารถมองไปข้างหน้า แต่กลับคุณสามารถย้อนกลับสตริงก่อนแล้วจึงทำ lookahead แน่นอนว่าจะต้องมีงานอีกมาก


8
คำตอบนี้สามารถใช้การปรับปรุงได้จริงๆ ดูเหมือนความคิดเห็นเพิ่มเติมกับฉัน
mickmackusa

2

นี่เป็นวิธีแก้ปัญหาที่เทียบเท่ากับคำตอบของ Tim Pietzcker (ดูความเห็นของคำตอบเดียวกัน):

^(?!.*filename\.js$).*\.js$

มันหมายถึงการแข่งขันยกเว้น*.js*filename.js

ในการเข้าสู่โซลูชันนี้คุณสามารถตรวจสอบว่ารูปแบบเชิงลบใด ๆ ที่อยู่ด้านหลังแยกออกจากนั้นแยกรูปแบบเหล่านี้ทั้งหมดด้วยค่าติดตั้งเชิงลบ


-1

ด้านล่างเป็นตัวเลือกที่เป็นประโยชน์อย่างมากสำหรับ JavaScript ซึ่งแสดงวิธีการจับนามสกุลของคนที่มี 'Michael' เป็นชื่อจริง

1) รับข้อความนี้:

const exampleText = "Michael, how are you? - Cool, how is John Williamns and Michael Jordan? I don't know but Michael Johnson is fine. Michael do you still score points with LeBron James, Michael Green Miller and Michael Wood?";

รับอาร์เรย์ของชื่อบุคคลที่มีชื่อว่า Michael ผลลัพธ์ควรเป็น:["Jordan","Johnson","Green","Wood"]

2) โซลูชัน:

function getMichaelLastName2(text) {
  return text
    .match(/(?:Michael )([A-Z][a-z]+)/g)
    .map(person => person.slice(person.indexOf(' ')+1));
}

// or even
    .map(person => person.slice(8)); // since we know the length of "Michael "

3) ตรวจสอบทางออก

console.log(JSON.stringify(    getMichaelLastName(exampleText)    ));
// ["Jordan","Johnson","Green","Wood"]

ตัวอย่างที่นี่: http://codepen.io/PiotrBerebecki/pen/GjwRoo

คุณสามารถลองใช้งานได้โดยใช้ตัวอย่างด้านล่าง

const inputText = "Michael, how are you? - Cool, how is John Williamns and Michael Jordan? I don't know but Michael Johnson is fine. Michael do you still score points with LeBron James, Michael Green Miller and Michael Wood?";



function getMichaelLastName(text) {
  return text
    .match(/(?:Michael )([A-Z][a-z]+)/g)
    .map(person => person.slice(8));
}

console.log(JSON.stringify(    getMichaelLastName(inputText)    ));

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