นิพจน์ปกติเพื่อค้นหาสตริงที่รวมอยู่ระหว่างอักขระสองตัวในขณะที่แยกตัวคั่น


294

ฉันต้องการแยกสตริงของชุดอักขระที่รวมอยู่ระหว่างตัวคั่นสองตัวโดยไม่ต้องส่งคืนตัวคั่น

ตัวอย่างง่ายๆควรมีประโยชน์:

เป้าหมาย : แยกสตริงย่อยระหว่างวงเล็บเหลี่ยมโดยไม่ต้องคืนค่าวงเล็บเอง

สตริงฐาน :This is a test string [more or less]

ถ้าฉันใช้ reg ต่อไปนี้ อดีต

\ [*. \]

[more or less]การแข่งขันคือ ฉันต้องได้รับเท่านั้นmore or less(โดยไม่ต้องวงเล็บ)

เป็นไปได้ที่จะทำหรือไม่


คำตอบ:


453

ทำได้ง่าย:

(?<=\[)(.*?)(?=\])

เทคนิคที่ใช้ lookaheads และ lookbehinds ดูLookahead และ Lookbehind ศูนย์ความกว้างยืนยัน รูปแบบประกอบด้วย:

  • ถูกนำหน้าด้วย [ที่ไม่ได้ถูกจับ (lookbehind);
  • กลุ่มที่ถูกจับไม่โลภ มันไม่โลภที่จะหยุดในตอนแรก]; และ
  • ตามด้วย] ที่ไม่ได้ถูกจับ (lookahead)

หรือคุณสามารถจับภาพสิ่งที่อยู่ระหว่างวงเล็บเหลี่ยม:

\[(.*?)\]

และคืนกลุ่มที่ถูกจับตัวแรกแทนการแข่งขันทั้งหมด


138
"ทำได้ง่าย" ฮ่า ๆ ! :) การแสดงออกปกติจะทำให้ฉันปวดหัวฉันมักจะลืมพวกเขาทันทีที่ฉันพบคนที่แก้ปัญหาของฉัน เกี่ยวกับโซลูชันของคุณ: งานแรกอย่างที่คาดไว้ที่สองไม่ได้รวมอยู่ในวงเล็บ ฉันใช้ C # อาจจะเป็นวัตถุ RegEx มีของตัวเอง "รส" ของเครื่องยนต์ regex ...
ดิเอโก

5
มันทำอย่างนั้นเพราะคุณดูที่การแข่งขันทั้งหมดแทนที่จะจับคู่กลุ่มแรก
cletus

ขอบคุณมากเว็บไซต์ที่มีประโยชน์มาก! ฉันจะเก็บไว้เป็นข้อมูลอ้างอิง :) ขออภัยหากฉันทำสับสน, C # การพัฒนาไม่ได้จริงๆหนึ่งในทักษะของฉัน ..
ดิเอโก

1
ใช้งานได้ไหมถ้าซับสตริงมีตัวคั่นด้วยหรือไม่ ยกตัวอย่างเช่นในThis is a test string [more [or] less]เรื่องนี้จะกลับมาmore [or] less?
gnzlbg

1
@gnzlbg ไม่มันจะส่งคืน "more [หรือ"
MerickOWA

52

หากคุณกำลังใช้งาน JavaScriptในการแก้ปัญหาครั้งแรกที่จัดไว้ให้โดย cletus, (?<=\[)(.*?)(?=\])จะไม่ทำงานเพราะ JavaScript ไม่สนับสนุนผู้ประกอบการ lookbehind

อย่างไรก็ตามโซลูชันที่สองทำงานได้ดี แต่คุณต้องได้รับองค์ประกอบที่สองที่ตรงกัน

ตัวอย่าง:

var regex = /\[(.*?)\]/;
var strToMatch = "This is a test string [more or less]";
var matched = regex.exec(strToMatch);

มันจะกลับมา:

["[more or less]", "more or less"]

ดังนั้นสิ่งที่คุณต้องการคือค่าที่สอง ใช้:

var matched = regex.exec(strToMatch)[1];

ในการส่งคืน:

"more or less"

2
จะเกิดอะไรขึ้นถ้ามีการแข่งขันหลายรายการของ [มากหรือน้อย] ในสตริง?

คำยืนยัน Lookbehind ได้รับการเพิ่มใน RegExp ใน ES2018
TheDarkIn1978

19

คุณเพียงแค่ต้อง 'จับ' บิตระหว่างวงเล็บ

\[(.*?)\]

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

my $string ='This is the match [more or less]';
$string =~ /\[(.*?)\]/;
print "match:$1\n";

ภาษาอื่นจะมีกลไกต่างกัน ตัวอย่างเช่น C # ใช้คลาสคอลเล็กชันการจับคู่ฉันเชื่อว่า


ขอบคุณ แต่โซลูชันนี้ใช้งานไม่ได้มันรวมถึงวงเล็บเหลี่ยมด้วย ในขณะที่ฉันเขียนความคิดเห็นของฉันไปยังโซลูชันของ Cletus อาจเป็นไปได้ว่าวัตถุ C # RegEx ตีความมันแตกต่างกัน ฉันไม่ใช่ผู้เชี่ยวชาญในภาษา C # ดังนั้นจึงเป็นเพียงการคาดเดาบางทีมันอาจเป็นเพราะฉันขาดความรู้ :)
Diego

11

[^\[] จับคู่อักขระใด ๆ ที่ไม่ใช่ [

+ตรงกับ 1 [หรือมากกว่าของสิ่งใดที่ไม่ได้เป็น สร้างกลุ่มของการแข่งขันเหล่านี้

(?=\])]lookahead บวก จับคู่กลุ่มที่ลงท้ายด้วย]โดยไม่รวมไว้ในผลลัพธ์

เสร็จสิ้น

[^\[]+(?=\])

พิสูจน์

http://regexr.com/3gobr

คล้ายกับโซลูชันที่เสนอโดย null แต่\]ไม่จำเป็นต้องเพิ่มเติม เป็นบันทึกเพิ่มเติมก็จะปรากฏขึ้น\ไม่จำเป็นต้องที่จะหลบหนีหลังจากที่[ ^เพื่อความสะดวกในการอ่านฉันจะทิ้งไว้

ไม่ทำงานในสถานการณ์ที่ตัวคั่นเหมือนกัน "more or less"ตัวอย่างเช่น.




3

ฉันมีปัญหาเดียวกันกับการใช้ regex กับสคริปต์ทุบตี ฉันใช้โซลูชันสองขั้นตอนโดยใช้ไพพ์ที่มีการใช้ grep -o

 '\[(.*?)\]'  

ก่อนอื่น

'\b.*\b'

เห็นได้ชัดว่าไม่มีประสิทธิภาพที่คำตอบอื่น ๆ แต่เป็นทางเลือก


3

อันนี้ใช้ได้กับตัวแยกวิเคราะห์นิพจน์ปกติของ javascript /[^[\]]+(?=])/g

เรียกใช้สิ่งนี้ในคอนโซล

var regex = /[^[\]]+(?=])/g;
var str = "This is a test string [more or less]";
var match = regex.exec(str);
match;

2

ฉันต้องการค้นหาสตริงระหว่าง / และ # แต่บางครั้ง # เป็นทางเลือก นี่คือ regex ที่ฉันใช้:

  (?<=\/)([^#]+)(?=#*)

0

นี่คือวิธีที่ฉันได้รับโดยไม่มี '[' และ ']' ใน C #:

        var text = "This is a test string [more or less]";
        //Getting only string between '[' and ']'
        Regex regex = new Regex(@"\[(.+?)\]");
        var matchGroups = regex.Matches(text);
        for (int i = 0; i < matchGroups.Count; i++)
        {
            Console.WriteLine(matchGroups[i].Groups[1]);
        }

ผลลัพธ์คือ:

more or less

-1

หากคุณต้องการแยกข้อความโดยไม่มีวงเล็บคุณสามารถใช้ bash awk

echo " [hola mundo] " | awk -F'[][]' '{print $2}'

ผลลัพธ์:

hola mundo

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