Saya perlu mencari string dan mengganti semua kemunculan %FirstName%
dan %PolicyAmount%
dengan nilai yang diambil dari database. Masalahnya adalah kapitalisasi FirstName bervariasi. Itu mencegah saya menggunakan String.Replace()
metode ini. Saya telah melihat halaman web pada subjek yang menyarankan
Regex.Replace(strInput, strToken, strReplaceWith, RegexOptions.IgnoreCase);
Namun untuk beberapa alasan ketika saya mencoba dan mengganti %PolicyAmount%
dengan $0
, penggantian tidak pernah terjadi. Saya berasumsi bahwa itu ada hubungannya dengan tanda dolar menjadi karakter yang dipesan di regex.
Apakah ada metode lain yang bisa saya gunakan yang tidak melibatkan sanitasi input untuk berurusan dengan karakter khusus regex?
Jawaban:
Dari MSDN
$ 0 - "Pengganti substring terakhir cocok dengan nomor kelompok (desimal)."
Dalam .NET Regular expressions group 0 selalu cocok. Untuk $ literal Anda perlu
sumber
Sepertinya
string.Replace
harus memiliki kelebihan yang membutuhkanStringComparison
argumen. Karena tidak, Anda dapat mencoba sesuatu seperti ini:sumber
ReplaceString
menjadiReplace
.oldValue == newValue == ""
.ReplaceString("œ", "oe", "", StringComparison.InvariantCulture)
melemparArgumentOutOfRangeException
.Semacam kelompok jawaban yang membingungkan, sebagian karena judul pertanyaannya sebenarnya jauh lebih besar daripada pertanyaan spesifik yang diajukan. Setelah membaca, saya tidak yakin ada jawaban beberapa suntingan dari mengasimilasi semua hal baik di sini, jadi saya pikir saya akan mencoba untuk menjumlahkan.
Berikut adalah metode ekstensi yang menurut saya menghindari jebakan yang disebutkan di sini dan memberikan solusi yang paling luas berlaku.
Begitu...
"œ".ReplaceCaseInsensitiveFind("oe", "")
meskipun ia mungkin memiliki perilaku yang sedikit berbeda dalam pikiran.Sayangnya, komentar @HA bahwa Anda harus
Escape
ketiganya tidak benar . Nilai awal dannewValue
tidak harus.Catatan: Anda harus melepaskan
$
nilai baru yang Anda sisipkan jika itu bagian dari apa yang kelihatannya merupakan penanda "nilai yang ditangkap" . Demikianlah tiga tanda dolar di Regex. Ganti di dalam Regex. Ganti [sic]. Tanpa itu, sesuatu seperti ini pecah ..."This is HIS fork, hIs spoon, hissssssss knife.".ReplaceCaseInsensitiveFind("his", @"he$0r")
Inilah kesalahannya:
Begini saja, saya tahu orang-orang yang nyaman dengan Regex merasa seperti penggunaannya menghindari kesalahan, tapi saya sering masih parsial untuk byte sniffing string (tetapi hanya setelah membaca Spolsky pada pengkodean ) untuk benar-benar yakin Anda mendapatkan apa yang Anda dimaksudkan untuk kasus penggunaan penting. Mengingatkan saya pada Crockford tentang " ekspresi reguler tidak aman " sedikit. Terlalu sering kita menulis regexps yang memungkinkan apa yang kita inginkan (jika kita beruntung), tetapi secara tidak sengaja memperbolehkan lebih banyak (misalnya, Apakah
$10
benar-benar string "nilai tangkapan" yang valid di regValue newValue saya, di atas?) Karena kami tidak cukup bijaksana . Kedua metode memiliki nilai, dan keduanya mendorong berbagai jenis kesalahan yang tidak disengaja. Seringkali mudah untuk meremehkan kompleksitas.Pelarian aneh itu
$
(dan ituRegex.Escape
tidak luput dari pola nilai yang ditangkap seperti yang$0
saya harapkan dalam nilai-nilai penggantian) membuat saya marah untuk sementara waktu. Pemrograman Sulit (c) 1842sumber
Inilah metode ekstensi. Tidak yakin di mana saya menemukannya.
sumber
Tampaknya metode termudah adalah dengan menggunakan metode Ganti yang dikirimkan bersama .Net dan telah ada sejak .Net 1.0:
Untuk menggunakan metode ini, Anda harus menambahkan Referensi ke kumpulan Microsoft.VisualBasic. Perakitan ini adalah bagian standar dari runtime .Net, ini bukan unduhan tambahan atau ditandai sebagai usang.
sumber
C. Dragon 76
berfungsi seperti yang diharapkan.sumber
Terinspirasi oleh jawaban cfeduke, saya membuat fungsi ini yang menggunakan IndexOf untuk menemukan nilai lama dalam string dan kemudian menggantinya dengan nilai baru. Saya menggunakan ini dalam skrip SSIS yang memproses jutaan baris, dan metode regex jauh lebih lambat dari ini.
sumber
Memperluas jawaban populer C. Dragon 76 dengan membuat kode menjadi ekstensi yang membebani
Replace
metode default .sumber
Berdasarkan jawaban Jeff Reddy, dengan beberapa optimisasi dan validasi:
sumber
versi yang mirip dengan C. Dragon, tetapi untuk jika Anda hanya perlu satu penggantian:
sumber
Berikut adalah opsi lain untuk menjalankan penggantian Regex, karena tidak banyak orang yang memperhatikan bahwa kecocokan memuat lokasi di dalam string:
sumber
sumber
Metode ekspresi reguler harus bekerja. Namun apa yang Anda juga dapat lakukan adalah huruf kecil string dari database, huruf kecil% variabel% yang Anda miliki, dan kemudian cari posisi dan panjang dalam string cased lebih rendah dari database. Ingat, posisi dalam string tidak berubah hanya karena cased lebih rendah
Kemudian menggunakan loop yang berjalan terbalik (lebih mudah, jika tidak, Anda harus tetap menghitung kemana titik kemudian pindah) hapus dari string cased yang tidak lebih rendah dari database% variabel% berdasarkan posisi dan panjang dan masukkan nilai penggantian.
sumber
(Karena semua orang mengambil kesempatan ini). Inilah versi saya (dengan cek nol, dan input dan penggantian yang benar hilang) ** Terinspirasi dari seluruh internet dan versi lain:
Pemakaian:
sumber
Biarkan saya membuat kasing saya dan kemudian Anda dapat mencabik-cabik saya jika Anda mau.
Regex bukan jawaban untuk masalah ini - terlalu lambat dan memori haus, relatif berbicara.
StringBuilder jauh lebih baik daripada string mangling.
Karena ini akan menjadi metode ekstensi untuk melengkapi
string.Replace
, saya percaya penting untuk mencocokkan cara kerjanya - karena itu melempar pengecualian untuk masalah argumen yang sama adalah penting seperti mengembalikan string asli jika penggantian tidak dilakukan.Saya percaya bahwa memiliki parameter StringComparison bukanlah ide yang baik. Saya memang mencobanya tetapi test case yang awalnya disebutkan oleh michael-liu menunjukkan masalah: -
Sementara IndexOf akan cocok, ada ketidakcocokan antara panjang pertandingan dalam string sumber (1) dan oldValue.Length (2). Ini memanifestasikan dirinya dengan menyebabkan IndexOutOfRange dalam beberapa solusi lain ketika oldValue.Length ditambahkan ke posisi pertandingan saat ini dan saya tidak dapat menemukan cara untuk mengatasi ini. Lagipula Regex gagal untuk mencocokkan case, jadi saya mengambil solusi pragmatis dari hanya menggunakan
StringComparison.OrdinalIgnoreCase
untuk solusi saya.Kode saya mirip dengan jawaban lain tetapi putaran saya adalah bahwa saya mencari kecocokan sebelum kesulitan membuat
StringBuilder
. Jika tidak ada yang ditemukan maka alokasi yang berpotensi besar dihindari. Kode kemudian menjadi ado{...}while
daripada awhile{...}
Saya telah melakukan beberapa pengujian ekstensif terhadap Jawaban lain dan ini keluar lebih cepat dan menggunakan sedikit memori.
sumber