I just want to replace with String.Empty if any Separators found in a given string.
class Program
{
private const string Separators = "-(). ";
static void Main(string[] args)
{
var number = Format("88 88-88)8.8(88");
}
public static string Format(string number)
{
return Regex.Replace(number, Separators, string.Empty);
}
}
Expected is : 8888888888 But was 88 88-88)8.8(88.
Did i miss something here.
Edit: if use
Separators.ToCharArray().ToList().ForEach(c => { number = number.Replace(c.ToString(), string.Empty);});
it works. But it could be better if i achieve with Regex.Replace.
When you are using a regular expression some characters have certain meanings. A dot means "any character", a dash means a range as in 0-9. I've escaped the characters and put them in a character set [] which means "any one in this set". I also renamed your Separators variable to better reflect what it is now.
Try this instead:
class Program
{
private const string SeparatorsRegex = #"[\-()\. ]";
static void Main(string[] args)
{
var number = Format("88 88-88)8.8(88");
}
public static string Format(string number)
{
return Regex.Replace(number, SeparatorsRegex, string.Empty);
}
}
Tested it in Expresso and this worked as expected. Its a great tool for regex dev:
http://www.ultrapico.com/Expresso.htm
(Ignore the terrible site design, it is a good util honest :P )
A further note, is that if you just want to strip everything that isnt a number then you could actually use this:
class Program
{
private const string StripNonNumbersRegex = #"[^\d]";
static void Main(string[] args)
{
var number = Format("88 88-88)8.8(88");
}
public static string Format(string number)
{
return Regex.Replace(number, StripNonNumbersRegex, string.Empty);
}
}
Regex.Replace() works on patterns, not separators. You are confusing it with String.Replace().
String.Replace(source, "-", string.empty) will work, but you will need to run this once per character.
Regex.Replace(source, pattern, string.empty) will work better, but you need to use a RegEx pattern, not simple list the characters.
Related
Objective: To get all the non-alphanumeric characters even though they are not contiguous.
Setup: I have a textbox on an ASP.Net page that calls a C# code behind method on TextChanged. This event handler runs the textbox input against a Regex pattern.
Problem: I cannot create the proper Regex pattern that extracts all the non-alphanumeric characters.
This is the string input: string titleString = #"%2##$%^&";
These are the C# Regex Patterns that I have tried:
string titlePattern = #"(\b[^A-Za-z0-9]+)"; results with ##$%^& (Note: if I use this input string %2#35%^&, then the above regex pattern will identify the # sign, and then the %^&), but never the leading % sign).
string titlePattern = #"(\A[^A-Za-z0-9]+)"; results with %
string titlePattern = #"(\b\W[^A-Za-z0-9]+)"; results with ##$%^&
Side Note: I am also running this in a MS Visual Studio Console Application with a foreach loop in an effort to get all invalid characters into a collection and I also test the input and pattern using the web site: http://regexstorm.net/tester
Use the replace method with your selection string.
EDIT: After a closer reading I see that you wanted the opposite string. Here's both.
using System;
using System.Text.RegularExpressions;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
string Source = #"H)*e/.?l\l{}*o ][W!~`##""or^-_=+ld!";
string Trash = #"[^a-zA-Z0-9]";
string InvertedTrash = #"[a-zA-Z0-9]";
Output(Source, Trash);
Console.WriteLine($"{System.Environment.NewLine}Opposite Day!{System.Environment.NewLine}");
Output(Source, InvertedTrash);
Console.ReadKey();
}
static string TakeOutTheTrash(string Source, string Trash)
{
return (new Regex(Trash)).Replace(Source, string.Empty);
}
static void Output(string Source, string Trash)
{
string Sanitized = TakeOutTheTrash(Source, Trash);
Console.WriteLine($"Started with: {Source}");
Console.WriteLine($"Ended with: {Sanitized}");
}
}
}
I've got an extension method that converts me ulong into a string value with some kind of encryption. I want to output them as they are just by using Console.WriteLine, in most scenarios it works but there is a problem with values with escapes characters. For example "(V\\\|RN" outputs just "(V\|RN".
var result = id.IdToCode();
Console.WriteLine(result);
or
Console.WriteLine(id.IdToCode());
The method IdToCode returns stringBuilder.ToString()
I've tried many combinations with putting somewhere # to return the string as it is but without any result. Maybe I should override the default behavior of Console.WriteLine or the stringBuilder.ToString() is the problem here?
Here is a screen of what I mean.
And below the code of IdToCode method:
public static string IdToCode(this ulong value)
{
const string charArray = #"1234890qwertyuiopbnmQWERTYUasdfghjklzxcvIOPASDFGHJKLZXCVBNM!+={}[]|\<>?##567$%^&*()-_";
StringBuilder stringBuilder = new StringBuilder();
ulong num = value;
while (num != 0UL)
{
ulong index = num % (ulong)charArray.Length;
num /= (ulong)charArray.Length;
stringBuilder.Insert(0, charArray[(int)index].ToString());
}
return stringBuilder.ToString();
}
I've changed the char array into different one but the general method it's the same as above.
The problem is you need to use the # in front of the string literal which actually adds the backslash to the StringBuilder.
There is no point in doing #id.IdToCode(), because when the string is returned, it already contains (V\|RN. The tooltip shows \\ because it shows the escaped eversion - meaning the single backslash.
One thing that is certain is that the problem can't be resolved here, but only inside the IdToCode method, where it actually originates.
Compare this (same as your code):
static void Main(string[] args)
{
var str = IdToCode();
Console.WriteLine();
}
public static string IdToCode()
{
return "(\\VN";
}
Hovering over str I see (\\VN - two backslashes, output is just one backslash - which is correct.
And this:
static void Main(string[] args)
{
var str = IdToCode();
Console.WriteLine();
}
public static string IdToCode()
{
return #"(\\VN";
}
Here the tooltip shows "(\\\\VN" which is again correct - there are two actual backslashes and console output is the desired (\\VN
How do convert a string to lowercase except for the first character?
Can this be completed with LINQ?
Thanks
If you only have one word in the string, you can use TextInfo.ToTitleCase. No need to use Linq.
As #Guffa noted:
This will convert any string to title case, so, "hello world" and "HELLO WORLD" would both be converted to "Hello World".
To achieve exectly what you asked (convert all characters to lower, except the first one), you can do the following:
string mostLower = myString.Substring(0, 1) + myString.Substring(1).ToLower();
This can be done with simple string operations:
s = s.Substring(0, 1) + s.Substring(1).ToLower();
Note that this does exactly what you asked for, i.e. it converts all characters to lower case except the first one that is left unchanged.
If you instead also want to change the first character to upper case, you would do:
s = s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower();
Note that this code assumes that there is at least two characters in the strings. If there is a possibility that it's shorter, you should of course test for that first.
String newString = new String(str.Select((ch, index) => (index == 0) ? ch : Char.ToLower(ch)).ToArray());
Use namespace: using System.Globalization;
...
string value = CultureInfo.CurrentCulture.TextInfo.ToTitleCase("hello");
EDIT
This code work only if its single word .For convert all character into lower except first letter check Guffa Answer.
string value = myString.Substring(0, 1) + myString.Substring(1).ToLower();
Not sure you can do it in linq here is a non-linq approach:
public static string FirstCap(string value)
{
string result = String.Empty;
if(!String.IsNullOrEmpty(value))
{
if(value.Length == 1)
{
result = value.ToUpper();
}
else
{
result = value.Substring(0,1).ToString().ToUpper() + value.Substring(1).ToLower();
}
}
return result;
}
based on guffa's example above (slightly amended). you could convert that to an extension method (please pardon the badly named method :)):
public static string UpperFirst(this string source)
{
return source.ToLower().Remove(0, 1)
.Insert(0, source.Substring(0, 1).ToUpper());
}
usage:
var myNewString = myOldString.UpperFirst();
// or simply referenced as myOldString.UpperFirst() where required
cheers guffa
var initialString = "Hello hOW r u?";
var res = string.Concat(initialString..ToUpper().Substring(0, 1), initialString.ToLower().Substring(1));
You can use an extension method:
static class StringExtensions
{
public static string ToLowerFirst(this string text)
=> !string.IsNullOrEmpty(text)
? $"{text.Substring(0, 1).ToLower()}{text.Substring(1)}"
: text;
}
Unit tests as well (using FluentAssertions and Microsoft UnitTesting):
[TestClass]
public class StringExtensionsTests
{
[TestMethod]
public void ToLowerFirst_ShouldReturnCorrectValue()
=> "ABCD"
.ToLowerFirst()
.Should()
.Be("aBCD");
[TestMethod]
public void ToLowerFirst_WhenStringIsEmpty_ShouldReturnCorrectValue()
=> string.Empty
.ToLowerFirst()
.Should()
.Be(string.Empty);
}
I have a string say
"Hello! world!"
I want to do a trim or a remove to take out the ! off world but not off Hello.
"Hello! world!".TrimEnd('!');
read more
EDIT:
What I've noticed in this type of questions that quite everyone suggest to remove the last char of given string. But this does not fulfill the definition of Trim method.
Trim - Removes all occurrences of
white space characters from the
beginning and end of this instance.
MSDN-Trim
Under this definition removing only last character from string is bad solution.
So if we want to "Trim last character from string" we should do something like this
Example as extension method:
public static class MyExtensions
{
public static string TrimLastCharacter(this String str)
{
if(String.IsNullOrEmpty(str)){
return str;
} else {
return str.TrimEnd(str[str.Length - 1]);
}
}
}
Note if you want to remove all characters of the same value i.e(!!!!)the method above removes all existences of '!' from the end of the string,
but if you want to remove only the last character you should use this :
else { return str.Remove(str.Length - 1); }
String withoutLast = yourString.Substring(0,(yourString.Length - 1));
if (yourString.Length > 1)
withoutLast = yourString.Substring(0, yourString.Length - 1);
or
if (yourString.Length > 1)
withoutLast = yourString.TrimEnd().Substring(0, yourString.Length - 1);
...in case you want to remove a non-whitespace character from the end.
The another example of trimming last character from a string:
string outputText = inputText.Remove(inputText.Length - 1, 1);
You can put it into an extension method and prevent it from null string, etc.
Try this:
return( (str).Remove(str.Length-1) );
In .NET 5 / C# 8:
You can write the code marked as the answer as:
public static class StringExtensions
{
public static string TrimLastCharacters(this string str) => string.IsNullOrEmpty(str) ? str : str.TrimEnd(str[^1]);
}
However, as mentioned in the answer, this removes all occurrences of that last character. If you only want to remove the last character you should instead do:
public static string RemoveLastCharacter(this string str) => string.IsNullOrEmpty(str) ? str : str[..^1];
A quick explanation for the new stuff in C# 8:
The ^ is called the "index from end operator". The .. is called the "range operator". ^1 is a shortcut for arr.length - 1. You can get all items after the first character of an array with arr[1..] or all items before the last with arr[..^1]. These are just a few quick examples. For more information, see https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8, "Indices and ranges" section.
string s1 = "Hello! world!";
string s2 = s1.Trim('!');
string helloOriginal = "Hello! World!";
string newString = helloOriginal.Substring(0,helloOriginal.LastIndexOf('!'));
string s1 = "Hello! world!"
string s2 = s1.Substring(0, s1.Length - 1);
Console.WriteLine(s1);
Console.WriteLine(s2);
Very easy and simple:
str = str.Remove( str.Length - 1 );
you could also use this:
public static class Extensions
{
public static string RemovePrefix(this string o, string prefix)
{
if (prefix == null) return o;
return !o.StartsWith(prefix) ? o : o.Remove(0, prefix.Length);
}
public static string RemoveSuffix(this string o, string suffix)
{
if(suffix == null) return o;
return !o.EndsWith(suffix) ? o : o.Remove(o.Length - suffix.Length, suffix.Length);
}
}
An example Extension class to simplify this: -
internal static class String
{
public static string TrimEndsCharacter(this string target, char character) => target?.TrimLeadingCharacter(character).TrimTrailingCharacter(character);
public static string TrimLeadingCharacter(this string target, char character) => Match(target?.Substring(0, 1), character) ? target.Remove(0,1) : target;
public static string TrimTrailingCharacter(this string target, char character) => Match(target?.Substring(target.Length - 1, 1), character) ? target.Substring(0, target.Length - 1) : target;
private static bool Match(string value, char character) => !string.IsNullOrEmpty(value) && value[0] == character;
}
Usage
"!Something!".TrimLeadingCharacter('X'); // Result '!Something!' (No Change)
"!Something!".TrimTrailingCharacter('S'); // Result '!Something!' (No Change)
"!Something!".TrimEndsCharacter('g'); // Result '!Something!' (No Change)
"!Something!".TrimLeadingCharacter('!'); // Result 'Something!' (1st Character removed)
"!Something!".TrimTrailingCharacter('!'); // Result '!Something' (Last Character removed)
"!Something!".TrimEndsCharacter('!'); // Result 'Something' (End Characters removed)
"!!Something!!".TrimLeadingCharacter('!'); // Result '!Something!!' (Only 1st instance removed)
"!!Something!!".TrimTrailingCharacter('!'); // Result '!!Something!' (Only Last instance removed)
"!!Something!!".TrimEndsCharacter('!'); // Result '!Something!' (Only End instances removed)
Slightly modified version of #Damian LeszczyĆski - Vash that will make sure that only a specific character will be removed.
public static class StringExtensions
{
public static string TrimLastCharacter(this string str, char character)
{
if (string.IsNullOrEmpty(str) || str[str.Length - 1] != character)
{
return str;
}
return str.Substring(0, str.Length - 1);
}
}
I took the path of writing an extension using the TrimEnd just because I was already using it inline and was happy with it...
i.e.:
static class Extensions
{
public static string RemoveLastChars(this String text, string suffix)
{
char[] trailingChars = suffix.ToCharArray();
if (suffix == null) return text;
return text.TrimEnd(trailingChars);
}
}
Make sure you include the namespace in your classes using the static class ;P and usage is:
string _ManagedLocationsOLAP = string.Empty;
_ManagedLocationsOLAP = _validManagedLocationIDs.RemoveLastChars(",");
If you want to remove the '!' character from a specific expression("world" in your case), then you can use this regular expression
string input = "Hello! world!";
string output = Regex.Replace(input, "(world)!", "$1", RegexOptions.Multiline | RegexOptions.Singleline);
// result: "Hello! world"
the $1 special character contains all the matching "world" expressions, and it is used to replace the original "world!" expression
My program will take arbitrary strings from the internet and use them for file names. Is there a simple way to remove the bad characters from these strings or do I need to write a custom function for this?
Ugh, I hate it when people try to guess at which characters are valid. Besides being completely non-portable (always thinking about Mono), both of the earlier comments missed more 25 invalid characters.
foreach (var c in Path.GetInvalidFileNameChars())
{
fileName = fileName.Replace(c, '-');
}
Or in VB:
'Clean just a filename
Dim filename As String = "salmnas dlajhdla kjha;dmas'lkasn"
For Each c In IO.Path.GetInvalidFileNameChars
filename = filename.Replace(c, "")
Next
'See also IO.Path.GetInvalidPathChars
To strip invalid characters:
static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
// Builds a string out of valid chars
var validFilename = new string(filename.Where(ch => !invalidFileNameChars.Contains(ch)).ToArray());
To replace invalid characters:
static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
// Builds a string out of valid chars and an _ for invalid ones
var validFilename = new string(filename.Select(ch => invalidFileNameChars.Contains(ch) ? '_' : ch).ToArray());
To replace invalid characters (and avoid potential name conflict like Hell* vs Hell$):
static readonly IList<char> invalidFileNameChars = Path.GetInvalidFileNameChars();
// Builds a string out of valid chars and replaces invalid chars with a unique letter (Moves the Char into the letter range of unicode, starting at "A")
var validFilename = new string(filename.Select(ch => invalidFileNameChars.Contains(ch) ? Convert.ToChar(invalidFileNameChars.IndexOf(ch) + 65) : ch).ToArray());
This question has been asked many times before and, as pointed out many times before, IO.Path.GetInvalidFileNameChars is not adequate.
First, there are many names like PRN and CON that are reserved and not allowed for filenames. There are other names not allowed only at the root folder. Names that end in a period are also not allowed.
Second, there are a variety of length limitations. Read the full list for NTFS here.
Third, you can attach to filesystems that have other limitations. For example, ISO 9660 filenames cannot start with "-" but can contain it.
Fourth, what do you do if two processes "arbitrarily" pick the same name?
In general, using externally-generated names for file names is a bad idea. I suggest generating your own private file names and storing human-readable names internally.
I agree with Grauenwolf and would highly recommend the Path.GetInvalidFileNameChars()
Here's my C# contribution:
string file = #"38?/.\}[+=n a882 a.a*/|n^%$ ad#(-))";
Array.ForEach(Path.GetInvalidFileNameChars(),
c => file = file.Replace(c.ToString(), String.Empty));
p.s. -- this is more cryptic than it should be -- I was trying to be concise.
Here's my version:
static string GetSafeFileName(string name, char replace = '_') {
char[] invalids = Path.GetInvalidFileNameChars();
return new string(name.Select(c => invalids.Contains(c) ? replace : c).ToArray());
}
I'm not sure how the result of GetInvalidFileNameChars is calculated, but the "Get" suggests it's non-trivial, so I cache the results. Further, this only traverses the input string once instead of multiple times, like the solutions above that iterate over the set of invalid chars, replacing them in the source string one at a time. Also, I like the Where-based solutions, but I prefer to replace invalid chars instead of removing them. Finally, my replacement is exactly one character to avoid converting characters to strings as I iterate over the string.
I say all that w/o doing the profiling -- this one just "felt" nice to me. : )
Here's the function that I am using now (thanks jcollum for the C# example):
public static string MakeSafeFilename(string filename, char replaceChar)
{
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
filename = filename.Replace(c, replaceChar);
}
return filename;
}
I just put this in a "Helpers" class for convenience.
If you want to quickly strip out all special characters which is sometimes more user readable for file names this works nicely:
string myCrazyName = "q`w^e!r#t#y$u%i^o&p*a(s)d_f-g+h=j{k}l|z:x\"c<v>b?n[m]q\\w;e'r,t.y/u";
string safeName = Regex.Replace(
myCrazyName,
"\W", /*Matches any nonword character. Equivalent to '[^A-Za-z0-9_]'*/
"",
RegexOptions.IgnoreCase);
// safeName == "qwertyuiopasd_fghjklzxcvbnmqwertyu"
Here's what I just added to ClipFlair's (http://github.com/Zoomicon/ClipFlair) StringExtensions static class (Utils.Silverlight project), based on info gathered from the links to related stackoverflow questions posted by Dour High Arch above:
public static string ReplaceInvalidFileNameChars(this string s, string replacement = "")
{
return Regex.Replace(s,
"[" + Regex.Escape(new String(System.IO.Path.GetInvalidPathChars())) + "]",
replacement, //can even use a replacement string of any length
RegexOptions.IgnoreCase);
//not using System.IO.Path.InvalidPathChars (deprecated insecure API)
}
static class Utils
{
public static string MakeFileSystemSafe(this string s)
{
return new string(s.Where(IsFileSystemSafe).ToArray());
}
public static bool IsFileSystemSafe(char c)
{
return !Path.GetInvalidFileNameChars().Contains(c);
}
}
Why not convert the string to a Base64 equivalent like this:
string UnsafeFileName = "salmnas dlajhdla kjha;dmas'lkasn";
string SafeFileName = Convert.ToBase64String(Encoding.UTF8.GetBytes(UnsafeFileName));
If you want to convert it back so you can read it:
UnsafeFileName = Encoding.UTF8.GetString(Convert.FromBase64String(SafeFileName));
I used this to save PNG files with a unique name from a random description.
private void textBoxFileName_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = CheckFileNameSafeCharacters(e);
}
/// <summary>
/// This is a good function for making sure that a user who is naming a file uses proper characters
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
internal static bool CheckFileNameSafeCharacters(System.Windows.Forms.KeyPressEventArgs e)
{
if (e.KeyChar.Equals(24) ||
e.KeyChar.Equals(3) ||
e.KeyChar.Equals(22) ||
e.KeyChar.Equals(26) ||
e.KeyChar.Equals(25))//Control-X, C, V, Z and Y
return false;
if (e.KeyChar.Equals('\b'))//backspace
return false;
char[] charArray = Path.GetInvalidFileNameChars();
if (charArray.Contains(e.KeyChar))
return true;//Stop the character from being entered into the control since it is non-numerical
else
return false;
}
From my older projects, I've found this solution, which has been working perfectly over 2 years. I'm replacing illegal chars with "!", and then check for double !!'s, use your own char.
public string GetSafeFilename(string filename)
{
string res = string.Join("!", filename.Split(Path.GetInvalidFileNameChars()));
while (res.IndexOf("!!") >= 0)
res = res.Replace("!!", "!");
return res;
}
I find using this to be quick and easy to understand:
<Extension()>
Public Function MakeSafeFileName(FileName As String) As String
Return FileName.Where(Function(x) Not IO.Path.GetInvalidFileNameChars.Contains(x)).ToArray
End Function
This works because a string is IEnumerable as a char array and there is a string constructor string that takes a char array.
Many anwer suggest to use Path.GetInvalidFileNameChars() which seems like a bad solution to me. I encourage you to use whitelisting instead of blacklisting because hackers will always find a way eventually to bypass it.
Here is an example of code you could use :
string whitelist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.";
foreach (char c in filename)
{
if (!whitelist.Contains(c))
{
filename = filename.Replace(c, '-');
}
}