I need to use a string for path for a file but sometimes there are forbidden characters in this string and I must replace them. For example, my string _title is rumbaton jonathan \"racko\" contreras.
Well I should replace the chars \ and ".
I tried this but it doesn't work:
_title.Replace(#"/", "");
_title.Replace(#"\", "");
_title.Replace(#"*", "");
_title.Replace(#"?", "");
_title.Replace(#"<", "");
_title.Replace(#">", "");
_title.Replace(#"|", "");
Since strings are immutable, the Replace method returns a new string, it doesn't modify the instance you are calling it on. So try this:
_title = _title
.Replace(#"/", "")
.Replace(#"""", "")
.Replace(#"*", "")
.Replace(#"?", "")
.Replace(#"<", "")
.Replace(#">", "")
.Replace(#"|", "");
Also if you want to replace " make sure you have properly escaped it.
Try regex
string illegal = "\"M\"\\a/ry/ h**ad:>> a\\/:*?\"| li*tt|le|| la\"mb.?";
string regexSearch = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
Regex r = new Regex(string.Format("[{0}]", Regex.Escape(regexSearch)));
illegal = r.Replace(illegal, "");
Before: "M"\a/ry/ h**ad:>> a/:?"| litt|le|| la"mb.?
After: Mary had a little lamb.
Also another answer from same post is much cleaner
private static string CleanFileName(string fileName)
{
return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty));
}
from How to remove illegal characters from path and filenames?
Or you could try this (probably terribly inefficient) method:
string inputString = #"File ~!##$%^&*()_+|`1234567890-=\[];',./{}:""<>? name";
var badchars = Path.GetInvalidFileNameChars();
foreach (var c in badchars)
inputString = inputString.Replace(c.ToString(), "");
The result will be:
File ~!##$%^&()_+`1234567890-=[];',.{} name
But feel free to add more chars to the badchars before running the foreach loop on them.
See http://msdn.microsoft.com/cs-cz/library/fk49wtc1.aspx:
Returns a string that is equivalent to the current string except that all instances of oldValue are replaced with newValue.
I have written a method to do the exact operation that you want and with much cleaner code.
The method
public static string Delete(this string target, string samples) {
if (string.IsNullOrEmpty(target) || string.IsNullOrEmpty(samples))
return target;
var tar = target.ToCharArray();
const char deletechar = '♣'; //a char that most likely never to be used in the input
for (var i = 0; i < tar.Length; i++) {
for (var j = 0; j < samples.Length; j++) {
if (tar[i] == samples[j]) {
tar[i] = deletechar;
break;
}
}
}
return tar.ConvertToString().Replace(deletechar.ToString(CultureInfo.InvariantCulture), string.Empty);
}
Sample
var input = "rumbaton jonathan \"racko\" contreras";
var cleaned = input.Delete("\"\\/*?><|");
Will result in:
rumbaton jonathan racko contreras
Ok ! I've solved my issue thanks to all your indications. This is my correction :
string newFileName = _artist + " - " + _title;
char[] invalidFileChars = Path.GetInvalidFileNameChars();
char[] invalidPathChars = Path.GetInvalidPathChars();
foreach (char invalidChar in invalidFileChars)
{
newFileName = newFileName.Replace(invalidChar.ToString(), string.Empty);
}
foreach (char invalidChar in invalidPathChars)
{
newFilePath = newFilePath.Replace(invalidChar.ToString(), string.Empty);
}
Thank you so musch everybody :)
Related
I would like to know how can i remove characters in a string from a specific index like :
string str = "this/is/an/example"
I want to remove all characters from the third '/' including so it would be like this:
str = "this/is/an"
I tried with substring and regex but i cant find a solution.
Using string operations:
str = str.Substring(0, str.IndexOf('/', str.IndexOf('/', str.IndexOf('/') + 1) + 1));
Using regex:
str = Regex.Replace(str, #"^(([^/]*/){2}[^/]*)/.*$", "$1");
To get "this/is/an":
string str = "this/is/an/example";
string new_string = str.Remove(str.LastIndexOf('/'));
If you need to keep the slash:
string str = "this/is/an/example";
string new_string = str.Remove(str.LastIndexOf('/')+1);
This expects there to be at least one slash. If none are present, you should check it beforehand to not throw an exception:
string str = "this.s.an.example";
string newStr = str;
if (str.Contains('/'))
newStr = str.Remove(str.LastIndexOf('/'));
If its importaint to get the third one, make a dynamic method for it, like this. Input the string, and which "folder" you want returned. 3 in your example will return "this/is/an":
static string ReturnNdir(string sDir, int n)
{
while (sDir.Count(s => s == '/') > n - 1)
sDir = sDir.Remove(sDir.LastIndexOf('/'));
return sDir;
}
This regex is the answer: ^[^/]*\/[^/]*\/[^/]*. It will capture the first three chunks.
var regex = new Regex("^[^/]*\\/[^/]*\\/[^/]*", RegexOptions.Compiled);
var value = regex.Match(str).Value;
I think the best way of doing that it's creating a extension
string str = "this/is/an/example";
str = str.RemoveLastWord();
//specifying a character
string str2 = "this.is.an.example";
str2 = str2.RemoveLastWord(".");
With this static class:
public static class StringExtension
{
public static string RemoveLastWord(this string value, string separator = "")
{
if (string.IsNullOrWhiteSpace(value))
return string.Empty;
if (string.IsNullOrWhiteSpace(separator))
separator = "/";
var words = value.Split(Char.Parse(separator));
if (words.Length == 1)
return value;
value = string.Join(separator, words.Take(words.Length - 1));
return value;
}
}
I need to get a characters after certain character match in a string. Please consider my Input string with expected resultant character set.
Sample String
*This is a string *with more than *one blocks *of values.
Resultant string
Twoo
I have done this
string[] SubIndex = aut.TagValue.Split('*');
string SubInd = "";
foreach (var a in SubIndex)
{
SubInd = SubInd + a.Substring(0,1);
}
Any help to this will be appreciated.
Thanks
LINQ solution:
var str = "*This is a string *with more than *one blocks *of values.";
var chars = str.Split(new char[] {'*'}, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.First());
var output = String.Join("", chars);
string s = "*This is a string *with more than *one blocks *of values.";
string[] splitted = s.Split(new char[] { '*' }, StringSplitOptions.RemoveEmptyEntries);
string result = "";
foreach (string split in splitted)
result += split[0];
Console.WriteLine(result);
Below code should work
var s = "*This is a string *with more than *one blocks *of values."
while ((i = s.IndexOf('*', i)) != -1)
{
// Print out the next char
if(i<s.Length)
Console.WriteLine(s[i+1]);
// Increment the index.
i++;
}
String.Join("",input.Split(new char[]{'*'},StringSplitOptions.RemoveEmptyEntries)
.Select(x=>x.First())
);
string strRegex = #"(?<=\*).";
Regex myRegex = new Regex(strRegex, RegexOptions.Multiline | RegexOptions.Singleline);
string strTargetString = "*This is a string *with more than *one blocks *of values.";
StringBuilder sb = new StringBuilder();
foreach (Match myMatch in myRegex.Matches(strTargetString))
{
if (myMatch.Success) sb.Append(myMatch.Value);
}
string result = sb.ToString();
please see below...
char[] s3 = "*This is a string *with more than *one blocks *of values.".ToCharArray();
StringBuilder s4 = new StringBuilder();
for (int i = 0; i < s3.Length - 1; i++)
{
if (s3[i] == '*')
s4.Append(s3[i+1]);
}
Console.WriteLine(s4.ToString());
I have some string and I would like to replace the last .something with a new string. As example:
string replace = ".new";
blabla.test.bla.text.jpeg => blabla.test.bla.text.new
testfile_this.00001...csv => testfile_this.00001...new
So it doesn't matter how many ..... there are, I'd like to change only the last one and the string what after the last . is coming.
I saw in C# there is Path.ChangeExtension but its only working in a combination with a File - Is there no way to use this with a string only? Do I really need regex?
string replace = ".new";
string p = "blabla.test.bla.text.jpeg";
Console.WriteLine(Path.GetFileNameWithoutExtension(p) + replace);
Output:
blabla.test.bla.text.new
ChangeExtension should work as advertised;
string replace = ".new";
string file = "testfile_this.00001...csv";
file = Path.ChangeExtension(file, replace);
>> testfile_this.00001...new
You can use string.LastIndexOf('.');
string replace = ".new";
string test = "blabla.test.bla.text.jpeg";
int pos = test.LastIndexOf('.');
if(pos >= 0)
string newString = test.Substring(0, pos-1) + replace;
of course some checking is required to be sure that LastIndexOf finds the final point.
However, seeing the other answers, let me say that, while Path.ChangeExtension works, it doesn't feel right to me to use a method from a operating system dependent file handling class to manipulate a string. (Of course, if this string is really a filename, then my objection is invalid)
string s = "blabla.test.bla.text.jpeg";
s = s.Substring(0, s.LastIndexOf(".")) + replace;
No you don't need regular expressions for this. Just .LastIndexOf and .Substring will suffice.
string replace = ".new";
string input = "blabla.bla.test.jpg";
string output = input.Substring(0, input.LastIndexOf('.')) + replace;
// output = "blabla.bla.test.new"
Please use this function.
public string ReplaceStirng(string originalSting, string replacedString)
{
try
{
List<string> subString = originalSting.Split('.').ToList();
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < subString.Count - 1; i++)
{
stringBuilder.Append(subString[i]);
}
stringBuilder.Append(replacedString);
return stringBuilder.ToString();
}
catch (Exception ex)
{
if (log.IsErrorEnabled)
log.Error("[" + System.DateTime.Now.ToString() + "] " + System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + " :: " + System.Reflection.MethodBase.GetCurrentMethod().Name + " :: ", ex);
throw;
}
}
I am wondering what would be the best way to specify an array of characters like,
{
}
[
]
and then check a string for these and if they are there, to completely remove them.
if (compiler.Parser.GetErrors().Count == 0)
{
AstNode root = compiler.Parse(phrase.ToLower());
if (compiler.Parser.GetErrors().Count == 0)
{
try
{
fTextSearch = SearchGrammar.ConvertQuery(root, SearchGrammar.TermType.Inflectional);
}
catch
{
fTextSearch = phrase;
}
}
else
{
fTextSearch = phrase;
}
}
else
{
fTextSearch = phrase;
}
string[] brackets = brackets = new string[]
{
"{",
"}",
"[",
"]"
};
string[] errorChars = errorChars = new string[]
{
"'",
"&"
};
StringBuilder sb = new StringBuilder();
string[] splitString = fTextSearch.Split(errorChars, StringSplitOptions.None);
int numNewCharactersAdded = 0;
foreach (string itm in splitString)
{
sb.Append(itm); //append string
if (fTextSearch.Length > (sb.Length - numNewCharactersAdded))
{
sb.Append(fTextSearch[sb.Length - numNewCharactersAdded]); //append splitting character
sb.Append(fTextSearch[sb.Length - numNewCharactersAdded - 1]); //append it again
numNewCharactersAdded++;
}
}
string newString = sb.ToString();
A regular expression can do this far more easily:
var result = Regex.Replace(input, #"[[\]()]", "");
Using a character set ([...]) to match anyone of the characters in it and replace with nothing. Regex.Replace will replace all matches.
Another concise way is using Enumerable.Except to get the set difference of the Chars(assuming brackets are chars):
String newString = new String(oldString.Except(brackets).ToArray());
string str = "faslkjnro(fjrmn){ferqwe}{{";
char[] separators = new []{'[', ']','{','}' };
var sb = new StringBuilder();
foreach (var c in str)
{
if (!separators.Contains(c))
{
sb.Append(c);
}
}
return sb.ToString();
How about this:
string myString = "a12{drr[ferr]vgb}rtg";
myString = myString.Replace("[", "").Replace("{", "").Replace("]", "").Replace("}", "");
You end up with:
a12drrferrvgbrtg
I don't know if I understand your problem, but you can solve your problem with this:
string toRemove = "{}[]";
string result = your_string_to_be_searched;
foreach(char c in toRemove)
result = result.Replace(c.ToString(), "");
or with an extension method
static class Extensions
{
public static string RemoveAll(this string src, string chars)
{
foreach(char c in chars)
src= src.Replace(c.ToString(), "");
return src;
}
}
With this you can use string result = your_string_to_be_searched.RemoveAll("{}[]");
string charsToRemove = #"[]{}";
string pattern = string.Format("[{0}]", Regex.Escape(charsToRemove));
var result = Regex.Replace(input, pattern, "");
The primary advantage of this over some of the other similar answers is that you aren't bothered with determining which characters need to be escaped in RegEx; you can let the library take care of that for you.
You can do this in a pretty compact fashion like this:
string s = "ab{c[d]}";
char[] ca = new char[] {'{', '}', '[', ']'};
Array.ForEach(ca, e => s = s.Replace(e.ToString(), ""));
Or this:
StringBuilder s = new StringBuilder("ab{c[d]}");
char[] ca = new char[] {'{', '}', '[', ']'};
Array.ForEach(ca, e => s.Replace(e.ToString(), ""));
Taken from this answer: https://stackoverflow.com/a/12800424/1498669
Just use .Split() with the char[] of your desired removeables and recapture it with .Join() or .Concat()
char[] delChars = "[]{}<>()".ToCharArray();
string input = "some (crazy) string with brac[et]s in{si}de";
string output = string.Join(string.Empty, input.Split(delChars));
//or
string output = string.Concat(input.Split(delChars));
References:
https://learn.microsoft.com/en-us/dotnet/csharp/how-to/parse-strings-using-split
https://learn.microsoft.com/en-us/dotnet/csharp/how-to/concatenate-multiple-strings#code-try-4
What would an implementation of 'MagicFunction' look like to make the following (nunit) test pass?
public MagicFunction_Should_Prepend_Given_String_To_Each_Line()
{
var str = #"line1
line2
line3";
var result = MagicFunction(str, "-- ");
var expected = #"-- line1
-- line2
-- line3";
Assert.AreEqual(expected, result);
}
string MagicFunction(string str, string prepend)
{
str = str.Replace("\n", "\n" + prepend);
str = prepend + str;
return str;
}
EDIT:
As others have pointed out, the newline characters vary between environments. If you're only planning to use this function on files that were created in the same environment then System.Environment will work fine. However, if you create a file on a Linux box and then transfer it over to a Windows box you'll want to specify a different type of newline. Since Linux uses \n and Windows uses \r\n this piece of code will work for both Windows and Linux files. If you're throwing Macs into the mix (\r) you'll have to come up with something a little more involved.
Use .Select on a list of the lines.
private static string MagicFunction(string str, string prefix)
{
string[] lines = str.Split(new[] { '\n' });
return string.Join("\n", lines.Select(s => prefix + s).ToArray());
}
How about:
string MagicFunction(string InputText) {
public static Regex regex = new Regex(
"(^|\\r\\n)",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
// This is the replacement string
public static string regexReplace =
"$1-- ";
// Replace the matched text in the InputText using the replacement pattern
string result = regex.Replace(InputText,regexReplace);
return result;
}
var result = "-- " + str.Replace(Environment.NewLine, Environment.NewLine + "-- ");
if you want it cope with either Windows (\r\n) NewLines or Unix ones (\n) then:
var result = "-- " + str.Replace("\n", "\n-- ");
No need to touch the \r as it is to be left where it was before. If however you want to cross between Unix and Windows then:
var result = "-- " + str.Replace("\r","").Replace("\n", Enviornment.NewLine + "-- ");
Will do it and return the result in the local OS's format
You could do it like that :
public string MagicFunction2(string str, string prefix)
{
bool first = true;
using(StringWriter writer = new StringWriter())
using(StringReader reader = new StringReader(str))
{
string line;
while((line = reader.ReadLine()) != null)
{
if (!first)
writer.WriteLine();
writer.Write(prefix + line);
first = false;
}
return writer.ToString();
}
}
You could split the string by Environment.NewLine, and then add the prefix to each of those string, and then join them by Environment.NewLine.
string MagicFunction(string prefix, string orignalString)
{
List<string> prefixed = new List<string>();
foreach (string s in orignalString.Split(new[]{Environment.NewLine}, StringSplitOptions.None))
{
prefixed.Add(prefix + s);
}
return String.Join(Environment.NewLine, prefixed.ToArray());
}
How about this. It uses StringBuilder in case you are planning on prepending a lot of lines.
string MagicFunction(string input)
{
StringBuilder sb = new StringBuilder();
StringReader sr = new StringReader(input);
string line = null;
using(StringReader sr = new StringReader(input))
{
while((line = sr.ReadLine()) != null)
{
sb.Append(String.Concat("-- ", line, System.Environment.NewLine));
}
}
return sb.ToString();
}
Thanks all for your answers. I implemented the MagicFunction as an extension method. It leverages Thomas Levesque's answer but is enhanced to handle all major environments AND assumes you want the output string to use the same newline terminator of the input string.
I favored Thomas Levesque's answer (over Spencer Ruport's, Fredrik Mork's, Lazarus, and JDunkerley) because it was the best performing. I'll post performance results on my blog and link here later for those interested.
(Obviously, the function name of 'MagicFunctionIO' should be changed. I went with 'PrependEachLineWith')
public static string MagicFunctionIO(this string self, string prefix)
{
string terminator = self.GetLineTerminator();
using (StringWriter writer = new StringWriter())
{
using (StringReader reader = new StringReader(self))
{
bool first = true;
string line;
while ((line = reader.ReadLine()) != null)
{
if (!first)
writer.Write(terminator);
writer.Write(prefix + line);
first = false;
}
return writer.ToString();
}
}
}
public static string GetLineTerminator(this string self)
{
if (self.Contains("\r\n")) // windows
return "\r\n";
else if (self.Contains("\n")) // unix
return "\n";
else if (self.Contains("\r")) // mac
return "\r";
else // default, unknown env or no line terminators
return Environment.NewLine;
}