Alonso Contreras
Alonso Contreras

Reputation: 675

Remove specific characters except last

I have a text string and I want to replace the dots with underscores except for the last character found in the string.

Example:

input = "video.coffee.example.mp4"
result = "video_coffe_example.mp4"

I have a code but this replaces everything including the last character

first option failed

static string replaceForUnderScore(string file)
{
     return file = file.Replace(".", "_");
}

I implemented a second option that works for me but I find that it is very extensive and not very optimized

static string replaceForUnderScore(string file)
{
     string result = "";

     var splits = file.Split(".");
     var extension = splits.LastOrDefault();

     splits = splits.Take(splits.Count() - 1).ToArray();

     foreach (var strItem in splits)
     {
         result = result + "_" + strItem;
     }

     result = result.Substring(1, result.Length-1);
     string finalResult = result + "."+extension;

     return finalResult;
 }

Is there a better way to do it?

Upvotes: 0

Views: 710

Answers (5)

NazaRN
NazaRN

Reputation: 419

Regex will help you to do this.

Add the namespace using System.Text.RegularExpressions;

And use this code:

var regex = new Regex(Regex.Escape("."));
var newText = regex.Replace("video.coffee.example.mp4", "_", 2);

Here we specified the maximum number of times to replace the .

The output would be the following:

video_coffee_example.mp4

Additionally, you can update the code to replace any number of dots excluding the last one.

    var replaceChar = '.';
    var regex = new Regex(Regex.Escape(replaceChar.ToString()));
    var replaceWith = "_";
    // The text to process
    var text = "video.coffee.example.mp4";
    // Count how many chars to replace excluding extension
    var replaceCount = text.Count(s => s == replaceChar) - 1;
    var newText = regex.Replace(text, replaceWith, replaceCount);

Upvotes: 2

The fourth bird
The fourth bird

Reputation: 163207

You can replace all the dots with an underscore except for the last dot by asserting that there is still a dot present to the right when matching one.

string result = Regex.Replace(input, @"\.(?=[^.]*\.)", "_");

The result will be

video_coffee_example.mp4

Upvotes: 1

Nicholas Carey
Nicholas Carey

Reputation: 74177

The simplest (and probably fastest) way is just to iterate over the string:

static string replaceForUnderScore(string file)
{
  StringBuilder sb      = new StringBuilder( file.Length ) ;
  int           lastDot = -1 ;

  for ( int i = 0 ; i < file.Length ; ++i )
  {
    char c = file[i] ;

    // if we found a '.', replace it with '_' and save its position
    if ( c == '.' )
    {
      c       = '_' ;
      lastDot = i   ;
    }


    sb.Append( c ) ;

  }

  // if we changed any '.' to '_', convert the last such replacement back to '.'
  if ( lastDot >= 0 )
  {
    sb.Replace ( '.' , '_' , lastDot, 1 );
  }

  return sb.ToString();
}

Another approach would be to use System.IO.Path. It's certainly the most succinct:

static string replaceForUnderScore( string file )
{
  string ext  = Path.GetExtension( file ) ;
  string name = Path
                .GetFileNameWithoutExtension( file )
                .Replace( '.' , '_' )
                ;

  return Path.ChangeExtension( name , ext ) ;
}

Upvotes: 0

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

Since you work with files, I suggest using Path class: all we want is to change file name only while keeping extension intact:

static string replaceForUnderScore(string file) =>
  Path.GetFileNameWithoutExtension(file).Replace('.', '_') + Path.GetExtension(file);

Upvotes: 3

TechneWare
TechneWare

Reputation: 263

Off the top of my head but this might work.

return $"{file.Replace(".mp4","").Replace(".","_")}.mp4";

Upvotes: 0

Related Questions