Bagaimana cara mengabaikan spasi dalam string subjek ekspresi reguler?

107

Adakah cara sederhana untuk mengabaikan spasi dalam string target saat mencari kecocokan menggunakan pola ekspresi reguler? Misalnya, jika penelusuran saya untuk "kucing", saya ingin "c ats" atau "ca ts" untuk mencocokkan. Saya tidak dapat menghapus spasi sebelumnya karena saya perlu menemukan indeks awal dan akhir pertandingan (termasuk spasi apa pun) untuk menyorot kecocokan itu dan spasi apa pun harus ada di sana untuk tujuan pemformatan.

Steven
sumber

Jawaban:

124

Anda dapat menempelkan karakter spasi kosong \s*di antara setiap karakter lain di regex Anda. Meski dikabulkan, itu akan sedikit panjang.

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

Sam Dufel
sumber
Terima kasih, sepertinya itulah cara yang harus dilakukan. Tetapi saya baru menyadari bahwa saya hanya menginginkan karakter spasi kosong opsional jika mereka mengikuti baris baru. Jadi misalnya, "c \ n ats" atau "ca \ n ts" harus cocok. Tetapi tidak ingin "c ats" cocok jika tidak ada baris baru. Ada ide tentang bagaimana hal itu bisa dilakukan?
Steven
@ Steven, lihat bagaimana saya melakukannya di bawah ini, Anda dapat dengan mudah menyesuaikan solusi saya untuk kasus-kasus tertentu.
Bob
@chris Saya pikir, regex ini sangat ketat hanya untuk kucing, juga dapat ditulis untuk pencarian huruf seperti ini: ^([a-z]\s*)+$
Sandeep Kaur
9

Mengatasi komentar Steven atas jawaban Sam Dufel

Terima kasih, sepertinya itulah cara yang harus dilakukan. Tetapi saya baru menyadari bahwa saya hanya menginginkan karakter spasi kosong opsional jika mereka mengikuti baris baru. Jadi misalnya, "c \ n ats" atau "ca \ n ts" harus cocok. Tetapi tidak ingin "c ats" cocok jika tidak ada baris baru. Ada ide tentang bagaimana hal itu bisa dilakukan?

Ini harus melakukan trik:

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

Lihat halaman ini untuk semua variasi berbeda dari 'kucing' yang cocok.

Anda juga bisa menyelesaikan ini menggunakan kondisional , tetapi tidak didukung dalam ragam javascript regex.

Aurimas
sumber
3
Sangat jelek. Pasti ada cara yang lebih baik.
james.garriss
Anda bisa membuatnya lebih mudah dibaca dalam sintaks JS (meskipun teknik ini akan bekerja dalam bahasa lain) dengan:new RegExp('cats'.split('').join('(?:\n\s*)?'))
brianary
7

Meskipun jawaban yang diterima secara teknis benar, pendekatan yang lebih praktis, jika memungkinkan, adalah dengan hanya menghapus spasi dari ekspresi reguler dan string pencarian.

Jika Anda ingin menelusuri "kucing saya", alih-alih:

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

Kerjakan saja:

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

Peringatan: Anda tidak dapat mengotomatiskan ini pada ekspresi reguler hanya dengan mengganti semua spasi dengan string kosong karena hal itu dapat terjadi dalam negasi atau membuat ekspresi reguler Anda tidak valid.

Konrad Höffner
sumber
5

Anda bisa meletakkan \s*inbetween setiap karakter dalam string pencarian Anda jadi jika Anda mencari kucing Anda akan menggunakanc\s*a\s*t\s*s\s*s

Itu panjang tapi tentu saja Anda bisa membangun senar secara dinamis.

Anda dapat melihatnya bekerja di sini: http://www.rubular.com/r/zzWwvppSpE

Kludge
sumber
3

Jika Anda hanya ingin mengizinkan spasi, maka

\bc *a *t *s\b

harus melakukannya. Untuk juga mengizinkan tab, gunakan

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

Hapus \bjangkar jika Anda juga ingin menemukan catskata-kata seperti bobcatsatau catsup.

Tim Pietzcker
sumber
1

Pendekatan ini dapat digunakan untuk mengotomatiskan ini (solusi contoh berikut ini dalam python, meskipun jelas dapat diporting ke bahasa apapun):

Anda dapat menghapus spasi terlebih dahulu DAN menyimpan posisi karakter non spasi sehingga Anda dapat menggunakannya nanti untuk mengetahui posisi batas string yang cocok dalam string asli seperti berikut:

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'

Jika Anda ingin melangkah lebih jauh, Anda dapat membuat objek yang cocok dan mengembalikannya, jadi penggunaan helper ini akan lebih praktis.

Dan kinerja dari fungsi ini tentunya juga dapat dioptimalkan, contoh ini hanya untuk menunjukkan jalan menuju solusi.

Bob
sumber