ฉันจะจับคู่อักขระใด ๆ ข้ามหลายบรรทัดในนิพจน์ทั่วไปได้อย่างไร


356

ตัวอย่างเช่น regex นี้

(.*)<FooBar>

จะจับคู่:

abcde<FooBar>

แต่ฉันจะทำให้ตรงกับหลายบรรทัดได้อย่างไร

abcde
fghij<FooBar>

1
เพื่อชี้แจง เดิมทีฉันใช้ Eclipse เพื่อทำการค้นหาและแทนที่ในหลายไฟล์ สิ่งที่ฉันค้นพบโดยคำตอบด้านล่างคือปัญหาของฉันคือเครื่องมือไม่ใช่รูปแบบ regex
andyuk

2
ควรลบเครื่องหมาย "eclipse" ของคุณออกเนื่องจากมีใครมองหาโซลูชัน eclipse จะพบคำถามนี้ (เหมือนที่ฉันทำ) จากนั้นค้นหาโซลูชันที่ไม่ใช่ eclipse ตามที่ยอมรับ
acme

2
ตอนนี้ฉันกำลังค้นหาสิ่งนี้ในเครื่องมือค้นหาเพราะมีการพูดถึงคราส โอ้หนังสยองขวัญ
Brian Olsen

คำตอบ:


240

ขึ้นอยู่กับภาษา แต่ควรมีตัวแก้ไขที่คุณสามารถเพิ่มลงในรูปแบบ regex ใน PHP มันคือ:

/(.*)<FooBar>/s

sตอนท้ายทำให้เกิดจุดเพื่อให้ตรงกับทุกตัวอักษรรวมถึงการขึ้นบรรทัดใหม่


และถ้าฉันต้องการเพียงแค่ขึ้นบรรทัดใหม่และไม่ใช่ตัวละครทั้งหมด?
เกรซ

3
@ เกรซ: ใช้ \ n เพื่อจับคู่บรรทัดใหม่
Jeremy Ruten

5
การตั้งค่าสถานะไม่ถูกต้อง (อย่างน้อยตอนนี้) อย่างน้อยใน Chrome / V8 . แทนการใช้ / ([\ s \ S] *) <FooBar> / ชั้นเรียนตัวอักษร (พื้นที่การแข่งขันและไม่ใช่ช่องว่าง] แทนการจับคู่งวดดูคำตอบอื่น ๆ สำหรับข้อมูลเพิ่มเติม.
อัลเลน

8
@Allen - JavaScript ไม่รองรับsตัวปรับแต่ง แต่ให้ทำ[^]*เพื่อผลเหมือนกัน
Derek 朕會功夫

1
ใน Ruby ให้ใช้mตัวดัดแปลง
Ryan Buckley

358

ลองสิ่งนี้:

((.|\n)*)<FooBar>

มันเป็นพื้นว่า "ตัวละครหรือขึ้นบรรทัดใหม่" ซ้ำแล้วซ้ำอีกเป็นศูนย์หรือมากกว่าครั้ง


5
ขึ้นอยู่กับภาษาและ / หรือเครื่องมือที่คุณใช้ โปรดแจ้งให้เราทราบว่าคุณกำลังใช้งานอะไรเช่น Perl, PHP, CF, C #, sed, awk และอื่น ๆ อีกมากมาย
Ben Doom

39
ขึ้นอยู่กับจุดสิ้นสุดของสายคุณอาจต้อง((.|\n|\r)*)<FooBar>
Potherca

3
เขาบอกว่าเขากำลังใช้ Eclipse นี่เป็นทางออกที่ถูกต้องในความคิดของฉัน ฉันมีปัญหาเดียวกันและนี่แก้ไขได้
Danubian Sailor

4
ขวา - คำถามเกี่ยวกับคราสและแท็กก็เช่นกัน แต่ทางออกที่ยอมรับคือโซลูชัน PHP คุณควรจะเป็นทางออกที่ได้รับการยอมรับ ...
สุดยอด

16
นี่คือ regex ที่เลวร้ายที่สุดสำหรับการจับคู่อินพุตหลายบรรทัด โปรดอย่าใช้มันจนกว่าคุณจะใช้ ElasticSearch ใช้หรือ[\s\S]* (?s).*
Wiktor Stribiżew

88

คำถามคือ.รูปแบบสามารถจับคู่กับตัวละครใด ๆ ? คำตอบนั้นแตกต่างกันไปในแต่ละเครื่องยนต์ ความแตกต่างที่สำคัญคือไม่ว่าจะใช้รูปแบบโดยไลบรารี POSIX หรือไลบรารีที่ไม่ใช่ POSIX

หมายเหตุพิเศษเกี่ยวกับ : ไม่ถือว่าเป็นนิพจน์ทั่วไป แต่.ตรงกับอักขระที่นั่นเช่นเดียวกับเครื่องมือที่ใช้ POSIX

หมายเหตุอื่นเกี่ยวกับ และ : .ตรงกับอักขระใด ๆ ตามค่าเริ่มต้น ( สาธิต ): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');( tokensมีabcde\n fghijรายการ)

นอกจากนี้ในทุก regex ของไวยากรณ์เป็นจุดตรงกับตัวแบ่งบรรทัดตามค่าเริ่มต้น ไวยากรณ์ ECMAScript ของ Boost ช่วยให้คุณปิดการใช้งานด้วยregex_constants::no_mod_m( แหล่งที่มา )

ส่วน (เป็นแบบ POSIX) ใช้nตัวเลือก ( สาธิต ):select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual

เอ็นจินที่ใช้ POSIX :

เพียง.แล้วตรงกับแบ่งบรรทัดไม่จำเป็นต้องใช้การปรับเปลี่ยนใด ๆ ให้ดู( สาธิต )

( สาธิต )( สาธิต )(TRE, เอ็นจิ้นperl=TRUEพื้นฐาน R R ที่ไม่มีสำหรับฐาน R ที่มีperl=TRUEหรือสำหรับรูปแบบstringr / stringiให้ใช้ตัวดัดแปลงแบบอินไลน์) ( สาธิต ) ก็ปฏิบัติเช่นเดียวกัน (?s).

อย่างไรก็ตามเครื่องมือที่ใช้ POSIX ส่วนใหญ่จะประมวลผลบรรทัดต่อบรรทัด ดังนั้น.ไม่ตรงกับตัวแบ่งบรรทัดเพียงเพราะพวกเขาไม่อยู่ในขอบเขต นี่คือตัวอย่างบางส่วนวิธีการแทนที่:

  • - มีวิธีแก้ไขหลายวิธีที่แม่นยำที่สุด แต่ไม่ปลอดภัยมากคือsed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/'( H;1h;$!d;x;slurps ไฟล์ในหน่วยความจำ) หากต้องรวมทั้งบรรทัดsed '/start_pattern/,/end_pattern/d' file(การนำออกจากจุดเริ่มต้นจะจบลงด้วยการจับคู่รวมบรรทัด) หรือsed '/start_pattern/,/end_pattern/{{//!d;};}' file(ยกเว้นการจับคู่บรรทัด) ที่สามารถนำมาพิจารณาได้
  • - perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"( -0slurps ไฟล์ทั้งหมดในหน่วยความจำ-pพิมพ์ไฟล์หลังจากใช้สคริปต์ที่กำหนดโดย-e) โปรดทราบว่าการใช้-000peจะเลื่อนไฟล์และเปิดใช้งาน 'โหมดย่อหน้า' โดยที่ Perl ใช้บรรทัดใหม่ติดต่อกัน ( \n\n) เป็นตัวคั่นเรคคอร์ด
  • grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file- ที่นี่zช่วยให้ไฟล์ slurping, (?s)เปิดใช้งานโหมด DOTALL สำหรับ.รูปแบบ(?i)ช่วยให้กรณีโหมดตาย\Kละเว้นข้อความที่จับคู่เพื่อให้ห่างไกล*?เป็นปริมาณขี้เกียจตรงกับสถานที่ก่อน(?=<Foobar>)<Foobar>
  • - pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file( Mเปิดใช้งานไฟล์ slurping ที่นี่) หมายเหตุpcregrepเป็นทางออกที่ดีสำหรับgrepผู้ใช้Mac OS

ดูการสาธิต

เอ็นจินที่ไม่ใช้ POSIX :

  • - ใช้sตัวแก้ไขPCRE_DOTALL ตัวดัดแปลง : preg_match('~(.*)<Foobar>~s', $s, $m)( สาธิต )
  • - ใช้การRegexOptions.Singlelineตั้งค่าสถานะ ( สาธิต ):
    - var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
    -var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
  • - ใช้(?s)ตัวเลือกแบบอินไลน์:$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
  • - ใช้โมดิsฟายเออร์ (หรือ(?s)อินไลน์เวอร์ชั่นเมื่อเริ่มต้น) ( สาธิต ):/(.*)<FooBar>/s
  • - ใช้แฟล็กre.DOTALL(หรือre.S) หรือโมดิ(?s)ฟายเออร์ ( สาธิต ): m = re.search(r"(.*)<FooBar>", s, flags=re.S)(แล้วif m:, print(m.group(1)))
  • - ใช้Pattern.DOTALLตัวดัดแปลง (หรือการ(?s)ตั้งค่าสถานะอินไลน์) ( สาธิต ):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • - ใช้(?s)ตัวดัดแปลงในรูปแบบ ( สาธิต ):regex = /(?s)(.*)<FooBar>/
  • - ใช้(?s)ตัวดัดแปลง ( สาธิต ):"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
  • - ใช้[^]หรือแก้ไขปัญหา[\d\D]/ [\w\W]/ [\s\S]( สาธิต ):s.match(/([\s\S]*)<FooBar>/)[1]
  • ( std::regex) การใช้งาน[\s\S]หรือการแก้ปัญหา JS ( สาธิต ):regex rex(R"(([\s\S]*)<FooBar>)");
  • - ใช้วิธีการเช่นเดียวกับใน ([\s\S]*)<Foobar>JavaScript, ( หมายเหตุ : MultiLineคุณสมบัติของ RegExpวัตถุบางครั้งคิดว่าเป็นตัวเลือกที่อนุญาตให้.จับคู่ข้ามตัวแบ่งบรรทัดในขณะที่ในความเป็นจริงมันจะเปลี่ยนเฉพาะ^และ$พฤติกรรมเพื่อให้ตรงกับจุดเริ่มต้น / สิ้นสุดของสายมากกว่าสตริงเช่นเดียวกับใน JS regex ) พฤติกรรม.)

  • - ใช้ตัวดัดแปลง/m MULTILINE ( สาธิต ):s[/(.*)<Foobar>/m, 1]

  • - regexps พื้นฐาน R PCRE - การใช้งาน(?s): regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]( สาธิต )
  • - ฟังก์ชั่น in stringr/ stringiregex ที่ขับเคลื่อนด้วยเอนจิน ICU regex ใช้(?s): stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]( สาธิต )
  • - ใช้ตัวดัดแปลงแบบอินไลน์(?s)เมื่อเริ่มต้น ( สาธิต ):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • - ใช้dotMatchesLineSeparatorsหรือ (ง่ายกว่า) ส่งต่อ(?s)ตัวปรับแบบอินไลน์ไปยังรูปแบบ:let rx = "(?s)(.*)<Foobar>"
  • - เช่นเดียวกับ Swift (?s)ทำงานได้ง่ายที่สุด แต่นี่คือวิธีการใช้งานตัวเลือก :NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • , - ใช้(?s)ตัวดัดแปลง ( สาธิต ): "(?s)(.*)<Foobar>"(ใน Google Spreadsheets =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))

หมายเหตุ(?s) :

ในเอ็นจิ้นที่ไม่ใช่ POSIX ส่วนใหญ่สามารถใช้(?s)inline modifier (หรือตัวเลือกการตั้งค่าสถานะแบบฝัง) เพื่อบังคับ.ให้ตรงกับตัวแบ่งบรรทัด

หากวางไว้ที่จุดเริ่มต้นของรูปแบบ(?s)การเปลี่ยนแปลง bahavior ของทั้งหมด.ในรูปแบบ หาก(?s)ถูกวางไว้ที่ใดที่หนึ่งหลังจากการเริ่มต้นเท่านั้นที่.จะได้รับผลกระทบที่อยู่ไปทางขวาของมันเว้นแต่reนี้เป็นรูปแบบที่ส่งผ่านไปยังหลาม ใน Python reโดยไม่คำนึงถึง(?s)ตำแหน่งรูปแบบทั้งหมด.จะได้รับผลกระทบ ผลที่ได้คือหยุดใช้(?s) (?-s)กลุ่มที่แก้ไขสามารถใช้เพื่อส่งผลต่อช่วงของรูปแบบ regex ที่ระบุเท่านั้น (เช่นDelim1(?s:.*?)\nDelim2.*จะทำการ.*?จับคู่ครั้งแรกในการขึ้นบรรทัดใหม่และที่สอง.*จะตรงกับส่วนที่เหลือของบรรทัด)

POSIX note :

ในเอ็นจิน regex ที่ไม่ใช่ POSIX การจับคู่ char, [\s\S]/ [\d\D]/ [\w\W]constructs ใด ๆสามารถใช้ได้

ใน POSIX [\s\S]จะไม่จับคู่อักขระใด ๆ (เช่นใน JavaScript หรือเอนจินที่ไม่ใช่ POSIX) เนื่องจากลำดับการยกเว้น regex ไม่ได้รับการสนับสนุนภายในนิพจน์วงเล็บเหลี่ยม [\s\S]จะแยกเป็นนิพจน์วงเล็บที่ตรงกับถ่านเดียว\หรือหรือsS


5
คุณควรเชื่อมโยงไปยังภาพรวมที่ยอดเยี่ยมนี้จากหน้าโปรไฟล์ของคุณหรือบางสิ่ง (+1)
Jan

1
คุณอาจต้องการเพิ่มสิ่งนี้ในรายการเพิ่ม : ในเนมสเปซ regex_constants, flag_type_'s: perl = ECMAScript = JavaScript = JScript = :: เพิ่ม :: regbase :: ปกติ = 0 ซึ่งเป็นค่าเริ่มต้นที่ Perl โปรแกรมเมอร์จะตั้งค่านิยาม#define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_mแฟล็กฐานสำหรับแฟล็ก regex ของพวกเขาเพื่อแสดงว่า และ arbitor คือมักจะปรับเปลี่ยนแบบอินไลน์ ที่(?-sm)(?s).*ตั้งใหม่

1
คุณสามารถเพิ่มเพื่อทุบตีได้ไหม
Pasupathi Rajamanickam

2
@PasupathiRajamanickam Bash ใช้เอ็นจิ้น POSIX regex .ตรงกับอักขระใด ๆ ที่นั่น (รวมถึงตัวแบ่งบรรทัด) ดูการสาธิตทุบตีออนไลน์นี้
Wiktor Stribiżew

1
You rock - นี่คือ mini-tutorial แบบละเอียดที่สุดใน (ค่อนข้าง) regexp แบบซับซ้อนที่ฉันเคยเห็น คุณสมควรที่คำตอบของคุณจะกลายเป็นคำตอบที่ยอมรับได้! ความรุ่งโรจน์และคะแนนโหวตพิเศษสำหรับการรวมGoไว้ในคำตอบ!
Gwyneth Llewelyn

68

หากคุณใช้การค้นหา Eclipse คุณสามารถเปิดใช้งานตัวเลือก "DOTALL" เพื่อให้ '.' จับคู่อักขระใด ๆ รวมถึงตัวคั่นบรรทัด: เพียงเพิ่ม "(? s)" ที่จุดเริ่มต้นของสตริงการค้นหาของคุณ ตัวอย่าง:

(?s).*<FooBar>

1
ไม่ได้ทุกที่เฉพาะในรสชาติของ regex ที่สนับสนุนตัวดัดแปลงแบบอินไลน์และแน่นอนว่าไม่ใช่ใน Ruby ที่(?s)=>(?m)
Wiktor Stribiżew

อะไรเพื่อทุบตี?
Pasupathi Rajamanickam

38

ในหลายภาษาของ regex /[\S\s]*<Foobar>/จะทำในสิ่งที่คุณต้องการ แหล่ง


2
จากลิงก์นั้น: "JavaScript และ VBScript ไม่มีตัวเลือกในการสร้างอักขระตัวแบ่งบรรทัดที่ตรงกับจุดในภาษาเหล่านั้นคุณสามารถใช้คลาสอักขระเช่น [\ s \ S] เพื่อจับคู่อักขระใด ๆ " แทนการ ใช้ [\ s \ S] (จับคู่เว้นวรรคและไม่ใช่ช่องว่าง) แทน
อัลเลน

32

([\s\S]*)<FooBar>

จุดตรงกับทั้งหมดยกเว้นการขึ้นบรรทัดใหม่ (\ r \ n) ดังนั้นใช้ \ s \ S ซึ่งจะจับคู่อักขระทั้งหมด


นี้แก้ปัญหาหากคุณกำลังใช้ [text rangeOfString:regEx options:NSRegularExpressionSearch]Objective-C ขอบคุณ!
J. Costa

1
ใช้งานได้กับการค้นหา & แทนที่ regex ของ intelliJ ขอบคุณ
barclay

วิธีนี้ใช้ได้ผล แต่มันจะต้องเกิดขึ้นครั้งแรกของ<FooBar>
Ozkan


13

เรายังสามารถใช้

(.*?\n)*?

เพื่อจับคู่ทุกอย่างรวมถึงการขึ้นบรรทัดใหม่โดยไม่โลภ

สิ่งนี้จะทำให้บรรทัดใหม่เป็นตัวเลือก

(.*?|\n)*?

8

"."โดยปกติจะไม่ตรงกับตัวแบ่งบรรทัด เอ็นจิ้น regex ส่วนใหญ่อนุญาตให้คุณเพิ่มS-flag (หรือที่เรียกว่าDOTALLและSINGLELINE) เพื่อให้"."ตรงกับบรรทัดใหม่ [\S\s]ถ้าว่าล้มเหลวคุณสามารถทำสิ่งที่ชอบ



5
/(.*)<FooBar>/s

s เป็นสาเหตุให้ Dot (.) จับคู่การขึ้นบรรทัดใหม่


ดูเหมือนว่าสิ่งนี้ไม่ถูกต้อง (Chrome): text.match (/ a / s) SyntaxError: การตั้งค่าสถานะที่ไม่ถูกต้องให้กับตัวสร้างของ RegExp
อัลเลน

เพราะมันไม่รองรับเอ็นจิ้น JavaScript RegEx sธงอยู่ใน PCRE เครื่องยนต์ที่สมบูรณ์แบบที่สุด (ใช้ได้ใน Perl และ PHP) PCRE มี 10 ธง (และคุณสมบัติอื่น ๆ อีกมากมาย) ในขณะที่ JavaScript มีเพียง 3 ธง ( gmi)
Morgan Touverey Quilling

4

ในนิพจน์ทั่วไปที่ใช้ Java คุณสามารถใช้ [\s\S]


1
ไม่ว่าจะเป็นแบ็กสแลชหรือ?
พอลเดรเปอร์

พวกเขาไปที่ส่วนท้ายของนิพจน์ปกติไม่ใช่ภายในตัวอย่าง: / blah / s
RandomInsano

ฉันเดาว่าคุณหมายถึง JavaScript ไม่ใช่ Java ใช่ไหม เนื่องจากคุณสามารถเพิ่มการsตั้งค่าสถานะลงในรูปแบบใน Java และ JavaScript ไม่มีsแฟล็ก
3limin4t0r

3

โปรดทราบว่า(.|\n)*อาจมีประสิทธิภาพน้อยกว่า (ตัวอย่าง) [\s\S]*(หากภาษาของคุณรองรับการหลบหนีดังกล่าว) และกว่าการค้นหาวิธีระบุตัวแก้ไขที่ทำ ยังตรงกับบรรทัดใหม่ หรือคุณสามารถไปกับทางเลือก POSIXy [[:space:][:^space:]]*เช่น


3

ใช้ RegexOptions.Singleline มันเปลี่ยนความหมายของ เพื่อรวมบรรทัดใหม่

Regex.Replace (เนื้อหา, searchText, replaceText, RegexOptions.Singleline);



1

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

ในกรณีนี้ regex ที่กำหนดจะตรงกับสตริงทั้งหมดเนื่องจาก "<FooBar>" มีอยู่ ขึ้นอยู่กับข้อกำหนดเฉพาะของการใช้งาน regex ค่า $ 1 (ที่ได้รับจาก "(. *)") จะเป็น "fghij" หรือ "abcde \ nfghij" ดังที่คนอื่น ๆ กล่าวว่าการใช้งานบางอย่างช่วยให้คุณควบคุมได้ว่า "" จะตรงกับบรรทัดใหม่ให้คุณเลือก

การใช้นิพจน์ทั่วไปแบบอิงบรรทัดมักใช้สำหรับสิ่งต่าง ๆ เช่น command เช่น egrep


1

ฉันมีปัญหาเดียวกันและแก้ไขในอาจไม่ใช่วิธีที่ดีที่สุด แต่ใช้งานได้ ฉันแทนที่ตัวแบ่งบรรทัดทั้งหมดก่อนที่จะทำการแข่งขันที่แท้จริงของฉัน:

mystring= Regex.Replace(mystring, "\r\n", "")

ฉันกำลังจัดการ HTML ดังนั้นการขึ้นบรรทัดใหม่จึงไม่สำคัญกับฉันในกรณีนี้

ฉันลองทุกคำแนะนำข้างต้นโดยไม่มีโชคฉันใช้. Net 3.5 FYI


ฉันใช้. NET เช่นกันและ(\s|\S)ดูเหมือนจะทำเคล็ดลับสำหรับฉัน!
Vamshi Krishna

@VamshiKrishna ใน. NET ใช้(?s)เพื่อ.จับคู่ตัวอักษรใด ๆ อย่าใช้(\s|\S)สิ่งที่จะทำให้ประสิทธิภาพลดลง
Wiktor Stribiżew

1

ใน Javascript คุณสามารถใช้ [^] * เพื่อค้นหาอักขระที่เป็นศูนย์ถึงไม่สิ้นสุดรวมถึงตัวแบ่งบรรทัด

$("#find_and_replace").click(function() {
  var text = $("#textarea").val();
  search_term = new RegExp("[^]*<Foobar>", "gi");;
  replace_term = "Replacement term";
  var new_text = text.replace(search_term, replace_term);
  $("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij&lt;Foobar&gt;</textarea>


0

โดยทั่วไป ไม่ตรงกับบรรทัดใหม่ดังนั้นให้ลอง((.|\n)*)<foobar>


3
ไม่ทำอย่างนั้น หากคุณต้องการจับคู่ทุกอย่างรวมถึงตัวแยกบรรทัดให้ใช้ตัวดัดแปลง DOTALL (aka / s หรือ SingleLine) แฮ็ค (. | \ n) ไม่เพียงทำให้ regex มีประสิทธิภาพน้อยลงเท่านั้น แต่ยังไม่ถูกต้อง อย่างน้อยที่สุดก็ควรจับคู่ \ r (carriage return) และ \ n (linefeed) มีตัวคั่นบรรทัดอื่น ๆ เช่นกันแม้ว่าจะไม่ค่อยได้ใช้ แต่ถ้าคุณใช้ธง DOTALL คุณไม่ต้องกังวลกับมัน
อลันมัวร์

1
\ R คือการจับคู่ที่ไม่ขึ้นกับแพลตฟอร์มสำหรับการขึ้นบรรทัดใหม่ใน Eclipse
opyate

@ คัดสรรคุณควรโพสต์สิ่งนี้เป็นคำตอบเนื่องจากอัญมณีเล็ก ๆ นี้มีประโยชน์อย่างเหลือเชื่อ
jeckhart

คุณสามารถลองสิ่งนี้แทน มันจะไม่ตรงกับเครื่องหมายวงเล็บด้านในและพิจารณาตัวเลือก\rด้วย:((?:.|\r?\n)*)<foobar>
ssc-hrep3

0

ฉันต้องการจับคู่เฉพาะถ้าบล็อกใน java

   ...
   ...
   if(isTrue){
       doAction();

   }
...
...
}

ถ้าฉันใช้ regExp

if \(isTrue(.|\n)*}

มันรวมวงเล็บปีกกาปิดสำหรับบล็อกวิธีดังนั้นฉันใช้

if \(!isTrue([^}.]|\n)*}

เพื่อแยกวงเล็บปิดออกจากการแข่งขันไวด์การ์ด


0

บ่อยครั้งที่เราต้องแก้ไขซับสตริงด้วยคำหลักสองสามคำกระจายข้ามบรรทัดก่อนหน้าสตริงย่อย พิจารณาองค์ประกอบ xml:

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>81</PercentComplete>
</TASK>

สมมติว่าเราต้องการที่จะปรับเปลี่ยน 81 เพื่อให้มีค่าอื่น ๆ บางพูด 40. ครั้งแรกที่ระบุ.UID.21..UID.แล้วข้ามตัวละครทุกตัวรวมถึงจน\n .PercentCompleted.รูปแบบนิพจน์ทั่วไปและข้อมูลจำเพาะแทนที่คือ:

String hw = new String("<TASK>\n  <UID>21</UID>\n  <Name>Architectural design</Name>\n  <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
//note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.

String  iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>40</PercentComplete>
</TASK>

กลุ่มย่อยน่าจะเป็นกลุ่มที่ขาดหายไป(.|\n) $3ถ้าเราทำให้มันไม่ใช่การจับภาพจาก(?:.|\n)นั้นคือ$3 (<PercentComplete>)ดังนั้นรูปแบบและreplaceSpecยังสามารถ:

pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")

และการเปลี่ยนทำงานอย่างถูกต้องเหมือนเดิม


0

โดยทั่วไปแล้วการค้นหาสามบรรทัดที่ต่อเนื่องกันใน Powershell จะมีลักษณะดังนี้:

$file = get-content file.txt -raw

$pattern = 'lineone\r\nlinetwo\r\nlinethree\r\n'     # "windows" text
$pattern = 'lineone\nlinetwo\nlinethree\n'           # "unix" text
$pattern = 'lineone\r?\nlinetwo\r?\nlinethree\r?\n'  # both

$file -match $pattern

# output
True

น่าประหลาดใจนี่เป็นข้อความยูนิกซ์ที่พรอมต์ แต่ข้อความ windows ในไฟล์:

$pattern = 'lineone
linetwo
linethree
'

ต่อไปนี้เป็นวิธีพิมพ์ปลายบรรทัด:

'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'

# output
lineone\nlinetwo\nlinethree\n

-2

ตัวเลือกที่ 1

วิธีหนึ่งคือใช้sแฟล็ก (เช่นเดียวกับคำตอบที่ยอมรับ):

/(.*)<FooBar>/s

ตัวอย่าง 1

ตัวเลือก 2

วิธีที่สองคือใช้mแฟล็ก (multiline) และรูปแบบใด ๆ ต่อไปนี้:

/([\s\S]*)<FooBar>/m

หรือ

/([\d\D]*)<FooBar>/m

หรือ

/([\w\W]*)<FooBar>/m

ตัวอย่าง 2

วงจร RegEx

jex.imเห็นภาพการแสดงออกปกติ:

ป้อนคำอธิบายรูปภาพที่นี่

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