Bir dizedeki bir kelimenin son geçtiği yeri değiştirme - C #


82

Bir dizedeki bir kelimenin son geçtiği yeri değiştirmem gereken bir problemim var.

Durum: Bana şu formatta bir dizge verildi:

string filePath ="F:/jan11/MFrame/Templates/feb11";

Sonra şu şekilde değiştiririm TnaName:

filePath = filePath.Replace(TnaName, ""); // feb11 is TnaName

Bu işe yarıyor, ancak benimle TnaNameaynı olduğunda bir sorunum var folder name. Bu olduğunda, bunun gibi bir dizeyle karşılaşıyorum:

F:/feb11/MFrame/Templates/feb11

Şimdi her iki oluşumunu da TnaNameile değiştirdi feb11. Dizimdeki kelimenin yalnızca son geçtiği yeri değiştirmenin bir yolu var mı?

Not: feb11bir TnaName- bir sorun değil başka sürecinden geldiği.


Tek amacınız yolun son kısmını değiştirmek mi? (yani, bundan /sonra?)
Simon Whitehead

Son parça değil, sadece sonuncusu TnaNamedeğil, yolda daha fazlası var, ancak soru için sadece örnek oluşturuyorum. Teşekkürler .
Shree

1
Bu dize her zaman bir şeye giden yol mudur? Varsa System.IO.Path sınıfını kullanmayı düşünün.
Yuriy Rozhovetskiy

Evet dize her zaman bir şeye giden yol.
Shree

Yanıtlar:


179

İşte bir dizenin son oluşumunu değiştirecek işlev

public static string ReplaceLastOccurrence(string Source, string Find, string Replace)
{
        int place = Source.LastIndexOf(Find);

        if(place == -1)
           return Source;

        string result = Source.Remove(place, Find.Length).Insert(place, Replace);
        return result;
}
  • Source İşlemi yapmak istediğiniz dizedir.
  • Find değiştirmek istediğiniz dizedir.
  • Replace değiştirmek istediğiniz dizedir.

Genel işlev için çok teşekkürler. İşe yarıyor ve @ Simon'a da katılıyorum.
Shree

6
dikkat, belki eşleşme yoktur (örn. Place == -1)
Alireza Noori

7
Eşleşme bulunmaması durumunda kaynağı döndürmek boş dizeden daha mantıklıdır.
Sasha

2
"Return Source" döndürmelisiniz; "return sting.Empty" yerine; çünkü Bul dizesi bulunmazsa mantıksal olarak başarısız olur.
Jignesh Variya

1
Bunu arasına ekleyin (ve Source dizesi olarak: public static string ReplaceLastOccurance(this string Source...ve herhangi bir dizge için dizenin son oluşumunu değiştirmek için kullanabileceğiniz şık bir uzantı yönteminiz var.
beaudetious

12

string.LastIndexOf()Dizenin son oluşumunun dizinini bulmak için kullanın ve ardından çözümünüzü aramak için alt dizeyi kullanın.


7

Değiştirmeyi manuel olarak yapmanız gerekir:

int i = filePath.LastIndexOf(TnaName);
if (i >= 0)
    filePath = filePath.Substring(0, i) + filePath.Substring(i + TnaName.Length);

3

Regex'in neden kullanılamadığını anlamıyorum:

public static string RegexReplace(this string source, string pattern, string replacement)
{
  return Regex.Replace(source,pattern, replacement);
}

public static string ReplaceEnd(this string source, string value, string replacement)
{
  return RegexReplace(source, $"{value}$", replacement);
}

public static string RemoveEnd(this string source, string value)
{
  return ReplaceEnd(source, value, string.Empty);
}

Kullanım:

string filePath ="F:/feb11/MFrame/Templates/feb11";
filePath = filePath.RemoveEnd("feb11"); // F:/feb11/MFrame/Templates/
filePath = filePath.ReplaceEnd("feb11","jan11"); // F:/feb11/MFrame/Templates/jan11

1
Regex.Escape () değerini almalısınız.
jcox

Demek istediğin, return Regex.Replace(Regex.Replace(source),pattern, replacement);?
Toddmo

Birinin ReplaceEnd ("(foobar)", ")", "thenewend") çağırdığını varsayalım. İşleviniz atacak, çünkü ") $" geçersiz bir normal ifade. Bu işe yarar: return RegexReplace (kaynak, Regex.Escape (değer) + "$", değiştirme); RemoveEnd'iniz için aynı hikaye.
jcox

@jcox, çift kaçıştan nasıl kaçınacağımı çözemedim, her işlev herkese açık, bu yüzden birden fazla potansiyel çağrı yolumuz var. Benim durumumda, onu özel karakterler için kullanmıyordum, ama ne demek istediğini anlıyorum.
Toddmo

@toddmo Ben ReplaceEnd ve RemoveEnd Regex.Replace doğrudan çağırırdım. Yine de konu dışı; İnsanların, bir normal ifade kalıbına kullanıcı girişi eklemenin zor olabileceğinin farkında olmalarını istiyorum. XML veya SQL'e girdi enjekte etmeye benzer şekilde - bir kaçış mekanizması olması gerekir.
jcox

1

Ad alanından bir Pathsınıf kullanabilirsiniz System.IO:

string filePath = "F:/jan11/MFrame/Templates/feb11";

Console.WriteLine(System.IO.Path.GetDirectoryName(filePath));

0

Çözüm, tek bir hat ile daha da basit bir şekilde uygulanabilir:

 static string ReplaceLastOccurrence(string str, string toReplace, string replacement)
    {
        return Regex.Replace(str, $@"^(.*){toReplace}(.*?)$", $"$1{replacement}$2");
    }

Böylelikle, normal ifade yıldız işareti operatörünün açgözlülüğünden yararlanıyoruz. İşlev şu şekilde kullanılır:

var s = "F:/feb11/MFrame/Templates/feb11";
var tnaName = "feb11";
var r = ReplaceLastOccurrence(s,tnaName, string.Empty);

0
var lastIndex = filePath.LastIndexOf(TnaName);

filePath = filePath.Substring(0, lastIndex);

2
Yalnızca kod yanıtları soruyu yanıtlasa da, kodunuz için bağlam, bu kodun neden çalıştığının bir nedeni ve daha fazla okuma için belgelere bazı referanslar sağlayarak yanıtınızın kalitesini önemli ölçüde artırabilirsiniz. Gönderen Yanıt Nasıl : "Brevity kabul edilebilir, ancak daha dolgun açıklamalar iyidir."
Pranav Hosangadi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.