จะละเว้นช่องว่างในสตริงหัวเรื่องนิพจน์ทั่วไปได้อย่างไร


107

มีวิธีง่ายๆในการละเว้นช่องว่างในสตริงเป้าหมายเมื่อค้นหารายการที่ตรงกันโดยใช้รูปแบบนิพจน์ทั่วไปหรือไม่? ตัวอย่างเช่นหากการค้นหาของฉันคือ "แมว" ฉันต้องการให้ "c ats" หรือ "ca ts" ตรงกัน ฉันไม่สามารถตัดช่องว่างออกก่อนได้เนื่องจากฉันต้องหาดัชนีเริ่มต้นและจุดสิ้นสุดของการจับคู่ (รวมถึงช่องว่างใด ๆ ) เพื่อเน้นการจับคู่นั้นและต้องมีช่องว่างเพื่อจุดประสงค์ในการจัดรูปแบบ

คำตอบ:


124

คุณสามารถติดอักขระเว้นวรรคที่เป็นตัวเลือก\s*ระหว่างอักขระอื่น ๆ ใน regex ของคุณได้ แม้ว่าจะได้รับ แต่ก็จะยาวไปหน่อย

/cats/ -> /c\s*a\s*t\s*s/


ขอบคุณดูเหมือนว่าจะเป็นวิธีที่จะไป แต่ฉันเพิ่งรู้ว่าฉันต้องการเฉพาะอักขระช่องว่างที่เป็นทางเลือกถ้ามันขึ้นบรรทัดใหม่ ตัวอย่างเช่น "c \ n ats" หรือ "ca \ n ts" ควรตรงกัน แต่ไม่ต้องการให้ "c ats" ตรงกันถ้าไม่มีการขึ้นบรรทัดใหม่ ความคิดใด ๆ เกี่ยวกับวิธีการที่จะทำได้?
Steven

@Steven ดูวิธีที่ฉันทำด้านล่างนี้คุณสามารถปรับวิธีแก้ปัญหาของฉันให้เข้ากับกรณีเฉพาะดังกล่าว
Bob

@chris ฉันคิดว่า regex นี้เข้มงวดมากสำหรับแมวเท่านั้น แต่ยังสามารถเขียนเพื่อค้นหาตัวอักษรเช่นนี้: ^([a-z]\s*)+$
Sandeep Kaur

9

กล่าวถึงความคิดเห็นของ Steven ต่อคำตอบของ Sam Dufel

ขอบคุณดูเหมือนว่าจะเป็นวิธีที่จะไป แต่ฉันเพิ่งรู้ว่าฉันต้องการเฉพาะอักขระช่องว่างที่เป็นทางเลือกถ้ามันขึ้นบรรทัดใหม่ ตัวอย่างเช่น "c \ n ats" หรือ "ca \ n ts" ควรตรงกัน แต่ไม่ต้องการให้ "c ats" ตรงกันถ้าไม่มีการขึ้นบรรทัดใหม่ ความคิดใด ๆ เกี่ยวกับวิธีการที่จะทำได้?

สิ่งนี้ควรทำเคล็ดลับ:

/c(?:\n\s*)?a(?:\n\s*)?t(?:\n\s*)?s/

ดูหน้านี้สำหรับรูปแบบต่างๆของ 'แมว' ที่เข้ากันได้

คุณยังสามารถแก้ปัญหานี้ได้โดยใช้เงื่อนไขแต่ไม่รองรับในรสชาติจาวาสคริปต์ของ regex


3
น่าเกลียดมาก ต้องมีวิธีที่ดีกว่านี้
james.garriss

คุณสามารถทำให้อ่านได้ง่ายขึ้นในไวยากรณ์ JS (แม้ว่าเทคนิคนี้จะใช้งานได้ในภาษาอื่น) ด้วย:new RegExp('cats'.split('').join('(?:\n\s*)?'))
brianary

7

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

หากคุณต้องการค้นหา "my cats" แทน:

myString.match(/m\s*y\s*c\s*a\*st\s*s\s*/g)

แค่ทำ:

myString.replace(/\s*/g,"").match(/mycats/g)

คำเตือน: คุณไม่สามารถทำสิ่งนี้โดยอัตโนมัติในนิพจน์ทั่วไปได้โดยเพียงแค่แทนที่ช่องว่างทั้งหมดด้วยสตริงว่างเนื่องจากอาจเกิดการปฏิเสธหรือทำให้นิพจน์ทั่วไปของคุณไม่ถูกต้อง


5

คุณสามารถใส่\s*ระหว่างอักขระทุกตัวในสตริงการค้นหาของคุณได้ดังนั้นหากคุณกำลังมองหาแมวที่คุณจะใช้c\s*a\s*t\s*s\s*s

มันยาว แต่คุณสามารถสร้างสตริงแบบไดนามิกได้แน่นอน

คุณสามารถดูการทำงานได้ที่นี่: http://www.rubular.com/r/zzWwvppSpE


3

หากคุณต้องการอนุญาตเฉพาะช่องว่างเท่านั้น

\bc *a *t *s\b

ควรทำ หากต้องการอนุญาตแท็บให้ใช้

\bc[ \t]*a[ \t]*t[ \t]*s\b

ถอด\bเบรกถ้าคุณยังต้องการที่จะหาcatsที่อยู่ในคำเช่นหรือbobcatscatsup


1

วิธีนี้สามารถใช้เพื่อทำให้สิ่งนี้เป็นไปโดยอัตโนมัติ (โซลูชันที่เป็นแบบอย่างต่อไปนี้อยู่ใน python แม้ว่าจะเห็นได้ชัดว่าสามารถพอร์ตไปยังภาษาใดก็ได้):

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

def regex_search_ignore_space(regex, string):
    no_spaces = ''
    char_positions = []

    for pos, char in enumerate(string):
        if re.match(r'\S', char):  # upper \S matches non-whitespace chars
            no_spaces += char
            char_positions.append(pos)

    match = re.search(regex, no_spaces)
    if not match:
        return match

    # match.start() and match.end() are indices of start and end
    # of the found string in the spaceless string
    # (as we have searched in it).
    start = char_positions[match.start()]  # in the original string
    end = char_positions[match.end()]  # in the original string
    matched_string = string[start:end]  # see

    # the match WITH spaces is returned.
    return matched_string

with_spaces = 'a li on and a cat'
print(regex_search_ignore_space('lion', with_spaces))
# prints 'li on'

หากคุณต้องการไปไกลกว่านั้นคุณสามารถสร้างวัตถุจับคู่และส่งคืนแทนดังนั้นการใช้ตัวช่วยนี้จะสะดวกกว่า

และแน่นอนว่าประสิทธิภาพของฟังก์ชั่นนี้ก็สามารถปรับให้เหมาะสมได้เช่นกันตัวอย่างนี้เป็นเพียงการแสดงเส้นทางไปยังโซลูชัน

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