จับคู่ทุกอย่างยกเว้นสตริงที่ระบุ


120

ฉันรู้ว่า regex ต่อไปนี้จะจับคู่ "สีแดง" "สีเขียว" หรือ "สีน้ำเงิน"

red|green|blue

มีวิธีที่ตรงไปตรงมาในการจับคู่ทุกอย่างยกเว้นสตริงที่ระบุไว้หลายรายการหรือไม่?


1
นิพจน์ทั่วไปบางรสชาติไม่สามารถทำได้ คุณทำงานอยู่ในสภาพแวดล้อมใด Java? Perl? .สุทธิ? ไลบรารี regex C / C ++ บางตัว? RDBMS?
FrustratedWithFormsDesigner

8
คุณไม่ได้บอกว่าต้องการเพื่ออะไร แต่คุณสามารถเปลี่ยนความรู้สึกของการดำเนินการ "จับคู่" ได้ สิ่งนี้จะไม่ช่วยคุณหากคุณพยายามทำการแยกส่วนที่ไม่ตรงกัน แต่เพื่อทดสอบว่าไม่มีสตริงที่ยกเว้นอยู่หรือไม่มันจะใช้งานได้หรือไม่if (!s.match(/red|green|blue/)) ... หมายเหตุ: ฉันรู้ว่า OP ไม่ได้ระบุภาษา / เฟรมเวิร์กดังนั้น ก่อนหน้านี้ควรถือเป็นตัวอย่างทั่วไปไม่ใช่ตัวอย่างที่กำหนด
tvanfosson

คำตอบ:


154

หากคุณต้องการตรวจสอบให้แน่ใจว่าสตริงไม่ใช่สีแดงสีเขียวหรือสีน้ำเงินคำตอบของ caskey คือ อย่างไรก็ตามสิ่งที่มักต้องการคือตรวจสอบให้แน่ใจว่าเส้นนั้นไม่มีสีแดงเขียวหรือน้ำเงินอยู่ในนั้น ด้วยเหตุนี้ให้ยึดนิพจน์ทั่วไปด้วย^และรวม.*ไว้ในผู้มองเชิงลบ:

^(?!.*(red|green|blue))

นอกจากนี้สมมติว่าคุณต้องการบรรทัดที่มีคำว่า "เครื่องยนต์" แต่ไม่มีสีใด ๆ :

^(?!.*(red|green|blue)).*engine

คุณอาจคิดว่าคุณสามารถแยก.*ส่วนหัวของนิพจน์ทั่วไปได้:

^.*(?!red|green|blue)engine     # Does not work

แต่คุณทำไม่ได้ คุณต้องมีทั้งสองอินสแตนซ์.*จึงจะทำงานได้


48

ขึ้นอยู่กับภาษา แต่โดยทั่วไปจะมีคำยืนยันเชิงลบที่คุณสามารถใส่ได้ดังนี้:

(?!red|green|blue)

(ขอบคุณสำหรับการแก้ไขไวยากรณ์ข้างต้นคือ Java และ Perl, YMMV ที่ถูกต้อง)


2
@caskey คำตอบที่สมบูรณ์คือการรวมกันของฉันและของคุณ ถ้าคุณต้องการรวมเข้าด้วยกันฉันจะลบของฉัน
Wayne Conrad

14
คำตอบนี้จะมีประโยชน์มากขึ้นถ้าคุณอธิบายมันเล็กน้อย ตัวอย่าง: What do "?" และ "!" หมายความว่าอย่างไร ทำไมคุณต้องมีกลุ่มการจับภาพ?
Lii

เป็น Python ที่ถูกต้องด้วย
Joe Mornin

เพิ่งใช้สิ่งนี้กับไลบรารี Delphi regEx และใช้งานได้ดังนี้: ^ (?! red | green | blue) นอกจากนี้ยังเป็นจริงสำหรับการทดสอบบนregex101.com ดังนั้นการพิมพ์ผิดข้างต้นหายไป ^ หรือมันใช้งานได้จริงใน Java / Perl / Python .. ?
Peter

33

จับคู่ทุกอย่างยกเว้นสตริงที่กำหนด

หากคุณต้องการจับคู่สตริงทั้งหมดที่คุณต้องการจับคู่ทุกอย่างยกเว้นบางสตริงคุณสามารถทำได้ดังนี้:

^(?!(red|green|blue)$).*$

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

คุณสามารถลองได้ที่นี่: https://regex101.com/r/rMbYHz/2

ทราบว่านี้จะทำงานเฉพาะกับเครื่องยนต์ regex ที่สนับสนุนlookahead เชิงลบ


23

คุณไม่จำเป็นต้องมองโลกในแง่ลบ มีตัวอย่างการทำงาน:

/([\s\S]*?)(red|green|blue|)/g

รายละเอียด:

  • [\s\S] - จับคู่ตัวละครใด ๆ
  • * - จับคู่จาก 0 ถึงไม่ จำกัด จากกลุ่มก่อนหน้า
  • ? - จับคู่ให้น้อยที่สุด
  • (red|green|blue|) - จับคู่คำใดคำหนึ่งหรือไม่มีอะไรเลย
  • g - ทำซ้ำรูปแบบ

ตัวอย่าง:

whiteredwhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredwhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredredgreenredgreenredgreenredgreenredgreenbluewhiteredbluewhiteredbluewhiteredbluewhiteredbluewhiteredwhite

จะ:

whitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhite

ทดสอบ: regex101.com


4
คุณสามารถลดจำนวนก้าวลงได้อย่างมากโดยการสลับ [\ s \ S] เป็นจุด ฉันรู้สึกสับสนมากว่าทำไมตัวอย่างอื่น ๆ จึงจับแต่ละคำทีละคำ วิธีนี้เป็นขั้นตอน regex ที่มากกว่าเล็กน้อย แต่ต้องใช้ขั้นตอนหลังการประมวลผลน้อยกว่ามาก
Zatronium

3
แต่สิ่งนี้ไม่ทำการจับคู่ (การตรวจสอบข้อความ) เพียงแค่ลบข้อความที่ระบุระหว่างการแทนที่
Marek R

โซลูชันนี้จะไม่แสดงผลข้อความสุดท้ายหลังจากคำที่ทราบ ดังนั้นไม่จำเป็นต้องเปรียบเทียบความเร็วมันเป็นเรื่องผิด
Wiktor Stribiżew

@ WiktorStribiżewแก้ไข
hlcs

10

ฉันมีคำถามเดียวกันวิธีแก้ปัญหาที่เสนอเกือบใช้งานได้ แต่มีปัญหา ในท้ายที่สุด regex ที่ฉันใช้คือ:

^(?!red|green|blue).*

ฉันทดสอบใน Javascript และ. NET

. * ไม่ควรวางไว้ในหัวมองเชิงลบเช่นนี้: ^ (?!. * แดง | เขียว | น้ำเงิน) มิฉะนั้นจะทำให้องค์ประกอบแรกทำงานแตกต่างจากส่วนที่เหลือ (เช่น "anotherred" จะไม่จับคู่ในขณะที่ " anothergreen "จะ)


3

จับคู่ข้อความใด ๆ แต่ผู้ที่ตรงกับรูปแบบมักจะประสบความสำเร็จกับการแยกสตริงที่มีรูปแบบ regex

ตัวอย่าง :

  • - Regex.Split(text, @"red|green|blue")หรือเพื่อกำจัดค่าว่างRegex.Split(text, @"red|green|blue").Where(x => !string.IsNullOrEmpty(x))(ดูการสาธิต )
  • - Regex.Split(text, "red|green|blue")หรือเพื่อลบรายการที่ว่างเปล่าRegex.Split(text, "red|green|blue").Where(Function(s) Not String.IsNullOrWhitespace(s))(ดูการสาธิตหรือการสาธิตนี้ที่รองรับ LINQ)
  • - text.split(/red|green|blue/)(ไม่จำเป็นต้องใช้โมดิgฟายเออร์ที่นี่!) (เพื่อกำจัดค่าว่างให้ใช้text.split(/red|green|blue/).filter(Boolean)) ดูการสาธิต
  • - text.split("red|green|blue")หรือ - เพื่อเก็บรายการว่างทั้งหมดไว้ - ใช้text.split("red|green|blue", -1)หรือเพื่อลบรายการที่ว่างทั้งหมดใช้รหัสเพิ่มเติมเพื่อลบออก (ดูการสาธิต )
  • - คล้ายกับ Java text.split(/red|green|blue/)เพื่อใช้รายการต่อท้ายทั้งหมดtext.split(/red|green|blue/, -1)และเพื่อลบรายการที่ว่างทั้งหมดให้ใช้text.split(/red|green|blue/).findAll {it != ""})(ดูการสาธิต )
  • - text.split(Regex("red|green|blue"))หรือหากต้องการลบรายการว่างให้ใช้text.split(Regex("red|green|blue")).filter{ !it.isBlank() }ดูการสาธิต
  • - text.split("red|green|blue")หรือเพื่อเก็บรายการที่ว่างเปล่าทั้งหมดไว้ใช้text.split("red|green|blue", -1)และเพื่อลบรายการที่ว่างทั้งหมดให้ใช้text.split("red|green|blue").filter(_.nonEmpty)(ดูการสาธิต )
  • - text.split(/red|green|blue/)ในการกำจัดค่าว่างให้ใช้.split(/red|green|blue/).reject(&:empty?)(และเพื่อให้ได้ทั้งรายการที่ว่างนำหน้าและต่อท้ายใช้-1เป็นอาร์กิวเมนต์ที่สอง.split(/red|green|blue/, -1)) (ดูการสาธิต )
  • - my @result1 = split /red|green|blue/, $text;หรือกับรายการว่างทั้งหมดต่อท้ายmy @result2 = split /red|green|blue/, $text, -1;หรือไม่มีรายการว่างmy @result3 = grep { /\S/ } split /red|green|blue/, $text;(ดูการสาธิต )
  • - preg_split('~red|green|blue~', $text)หรือpreg_split('~red|green|blue~', $text, -1, PREG_SPLIT_NO_EMPTY)ไม่แสดงรายการว่าง (ดูการสาธิต )
  • - re.split(r'red|green|blue', text)หรือเพื่อลบรายการที่ว่างเปล่าlist(filter(None, re.split(r'red|green|blue', text)))(ดูการสาธิต )
  • - ใช้regexp.MustCompile("red|green|blue").Split(text, -1)และหากคุณต้องการลบรายการที่ว่างเปล่าให้ใช้รหัสนี้ ดูการสาธิตไป

หมายเหตุ : หากรูปแบบของคุณมีการจับกลุ่มฟังก์ชัน / วิธีการแยก regex อาจทำงานแตกต่างกันไปขึ้นอยู่กับตัวเลือกเพิ่มเติม โปรดดูเอกสารวิธีการแบ่งที่เหมาะสมจากนั้น


0

ทั้งหมดยกเว้นคำว่า "สีแดง"

var href = '(text-1) (red) (text-3) (text-4) (text-5)';

var test = href.replace(/\((\b(?!red\b)[\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

ทั้งหมดยกเว้นคำว่า "สีแดง"

var href = '(text-1) (frede) (text-3) (text-4) (text-5)';

var test = href.replace(/\(([\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = p1.replace(/red/g, '');
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

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