!rm`.*$
Dengan satu regex, Retina berjalan dalam mode Match. Ini biasanya hanya mencetak jumlah kecocokan, tetapi dengan !
kami mengkonfigurasinya untuk mencetak kecocokan yang sebenarnya sebagai gantinya (dipisahkan oleh baris baris).
Regex sebenarnya hanyalah .*$
. .*
cocok dengan baris apa saja (berpotensi kosong), karena .
dapat cocok dengan karakter apa pun kecuali umpan baris. Saya akan ke $
dalam sebentar lagi.
Bagaimana kita membuatnya mencetak pertandingan secara terbalik? Dengan memanfaatkan mode pencocokan kanan-ke-kiri .NET, diaktifkan dengan r
. Ini berarti mesin regex mulai di akhir string ketika mencari yang cocok dan bekerja mundur.
Akhirnya, m
buatlah yang $
cocok dengan akhir baris, bukan akhir dari string. Mengapa kita membutuhkan itu? Masalahnya adalah .*
menghasilkan kecocokan yang asing. Pertimbangkan substitusi regex
s/a*/$0x/
diterapkan pada input baaababaa
. Anda akan berpikir ini akan menghasilkan baaaxbaxbaax
, tetapi sebenarnya memberi Anda baaaxxbaxxbaaxx
. Mengapa? Karena setelah mencocokkan aaa
kursor mesin adalah antara a
dan b
. Sekarang tidak dapat lagi cocok dengan a
s, tetapi a*
juga puas dengan string kosong. Ini berarti, setelah setiap pertandingan Anda mendapatkan pertandingan kosong yang lain.
Kami tidak ingin itu ada di sini, karena itu akan memperkenalkan baris kosong tambahan, jadi kami membuang kecocokan yang asing (yang berada di awal garis, karena mode kanan-ke-kiri) dengan mengharuskan kecocokan mencakup akhir garis.
tac
agak aneh ketika datang untuk mengikuti linefeeds. Ini mengubaha\nb\n
(trailing linefeed) menjadib\na\n
dana\nb
(tidak ada trafeed linefeed) menjadiba\n
. Apakah ini bagaimana seharusnya kode kita berperilaku?