C# variables inside of quotes - c#

With string interpolation, how do you handle variables piped into a command that contain spaces in them? For example, if you have a variable that has spaces in it (like a UNC path), how do you handle that?
This code works when no spaces are present in the "filePath" variable (i.e.; \ServerName\testfile.txt):
Ex: System.Diagnostics.Process.Start("net.exe", $"use X: \\{filePath} {pwd /USER:{usr}").WaitForExit();
As soon as you encounter a path that has spaces in it, however, the command above no longer works, because it's unable to find the path. Normally, I would apply quotes around a path containing spaces, to counter this (in other languages like PowerShell). How do you do something similar with C# interpolation.

C# 6.0+:
System.Diagnostics.Process.Start("net.exe", #$"use X: \\Servername\share {pwd} /USER:{usr}").WaitForExit();
C# < 6.0:
System.Diagnostics.Process.Start("net.exe", #"use X: \\Servername\share " + pwd + " /USER: " + usr).WaitForExit();

use the $
void Main()
{
string pwd = "test";
var myVar = $"This is a {pwd}";
var folder = "MyFolder";
var myVarWithPaths = $"C:\\{folder}";
Console.WriteLine(myVar);
Console.WriteLine(myVarWithPaths);
}
Output
This is a test
C:\MyFolder

C# 6.0 introduced string interpolation, which is used by prefixing a quoted string of text with the $ character.
e.g.
var i = 0;
var s = $"i = {i}";
// output: i = 0
You can also embed multiple interpolated strings, as well as conditions.
var i = 0;
var s = $"i is: {(i == 1 ? $"i is {1}" : "i is not 1")}";
This can be combined with string literals that are prefixed with #.
var i = 1;
var s = #$"c:\{i}\test";
Basically, you can write almost any normal expression statement in a interpolated string, such as calling methods:
var s = $"i is {GetValueOfI() - 100}";
For types that are not a System.String, the implementation of that types ToString() method will be used for the resulting value.
See: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated

Related

C# read path withoutI put / in each subfolder

I want to put file path in File.Copy(path)
How can I put the path and not add / every time?
In python I can put r to read the path and not add /:
open(r"path")
Is there anything similar in C Sharp?
Yes you can use the # operator: var path = #"c:\\APath\bier";
these are called verbatim strings:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/#regular-and-verbatim-string-literals
Edit:
Also when dealing with paths string interpolation may come in handy, in short its a way to substitute values in a string. Its the same as string.format but the syntax is better imo:
var hello = "Hello";
var world = "world";
var helloworldStringFormat = string.Format("{0} {1}", hello, world);
var helloworldStringInterpolation = $"{hello} {world}";
Also see: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/#string-interpolation
Any ways you can do things like this:
var someValue = "bier";
var path3 = $"c:\\APath\\{someValue}";
var path4 = string.Format(#"c:\APath\{0}", someValue);
Also check out the Path class for dealing with paths, and optionally the Directory class.
https://learn.microsoft.com/en-us/dotnet/api/system.io.path?view=net-5.0
https://learn.microsoft.com/en-us/dotnet/api/system.io.directory?view=net-5.0

How do I find a variable set of 5 numbers qualified by surrounding underscores?

I am pulling file names into a variable (#[User::FileName]) and attempting to extract the work order number (always 5 numbers with underscores on both sides) from that string. For example, a file name would look like - "ABC_2017_DEF_9_12_GHI_35132_S5160.csv". I want result to return "35132". I have found examples of how to do it such as this SUBSTRING(FileName,1,FINDSTRING(FileName,"_",1) - 1) but the underscore will not always be in the same location.
Is it possible to do this in the expression builder?
Answer:
public void Main()
{
string strFilename = Dts.Variables["User::FileName"].Value.ToString();
var RegexObj = new Regex(#"_([\d]{5})_");
var match = RegexObj.Match(strFilename);
if (match.Success)
{
Dts.Variables["User::WorkOrder"].Value = match.Groups[1].Value;
}
Dts.TaskResult = (int)ScriptResults.Success;
}
First of all, the example you have provided ABC_2017_DEF_9_12_GHI_35132_S5160.csv contains 4 numbers located between underscores:
2017 , 9 , 12 , 35132
I don't know if the filename may contains many a 5 digits number can occurs many times, so in my answer i will assume that the number you want to return is the last occurrence of the number made of 5 digits.
Solution
You have to use the Following Regular Expression:
(?:_)\K[0-9][0-9][0-9][0-9][0-9](?=_)
DEMO
Or as #MartinSmith Suggested (in a comment), you can use the following RegEx:
_([\d]{5})_
Implemeting RegEx in SSIS
First add another Variable (Ex: #[User::FileNumber])
Add a Script Task and choose #[User::Filename] variable as ReadOnlyVariable, and #[User:FileNumber] as ReadWriteVariable
Inside the script task use the following code:
using System.Text.RegularExpressions;
public void Main()
{
string strFilename = Dts.Variables["filename"].Value.ToString();
string strNumber;
var objRegEx = new Regex(#"(?:_)\K[0-9][0-9][0-9][0-9][0-9](?=_)");
var mc = objRegEx.Matches(strFilename);
//The last match contains the value needed
strNumber = mc[mc.Count - 1].Value;
Dts.Variables["FileNumber"].Value.ToString();
Dts.TaskResult = (int)ScriptResults.Success;
}
do the other pieces mean something?
anyway you can use a script task and split function.
pass in #fileName as readonly, and #WO as readwrite
string fn = Dts.Variables["fileName"].Value;
string[] parts = fn.Split('_');
//Assuming it's always the 7th part
// You could extract the other parts as well.
Dts.Variables["WO"].Value = part(6);
I would do this with a Script Transformation (or Script Task if this is not in a DataFlow) and use a Regex.

Replace content in first set of quotes found in string c#

I am working on a project that involves having to manipulate a bat file based on certain user produced parameters. The bat files themselves are created manually, with a static format. A basic example of a bat file would be:
cd \some\predefined\bat
start run_some_script "user_generated_argument" [other pre-defined arguments]
The "user_generated_argument" bit of the bat file is manipulated in C# by the following code:
string bat_text = File.ReadAllText(bat_path);
Regex regex = new Regex("(.*?)\".*\"(.*)");
string new_argument = "A new argument";
string new_bat = regex.Replace(bat_text , "$1\"" + new_argument + "\"$2", 1);
And that would produce the following:
cd \some\predefined\bat
start run_some_script "A new argument" [other pre-defined arguments]
which is the expected output.
However, the problem lies when one of the other pre-defined arguments after the first quoted argument is also in quotes when that is the case, it seems that the second quoted argument disappears. For example, if the bat file looks like:
cd \some\predefined\bat
start run_some_script "user_generated_argument" "a_predefined_quoted_argument" [other pre-defined arguments]
Running the same C# code from above would produce the following:
cd \some\predefined\bat
start run_some_script "A new argument" [other pre-defined arguments]
The "a_predefined_quoted_argument" would no longer be in the string.
I may be doing this completely wrong. How would I make the predefined quoted argument not disappear?
the problem is that your expression
\".*\"
is eager or greedy, taking everything between the first quote and the last quote it finds. To make it lazy or reluctant, put a ? after the *
like so (I used VB, which escapes double quotes by double double quotes)
Dim batfile As String = "cd \some\predefined\bat" & vbCrLf & "start run_some_script ""user_generated_argument"" ""a_predefined_quoted_argument"" [other pre-defined arguments]"
Dim regex As Regex = New Regex("(.*?)"".*?""(.*)")
Dim new_argument As String = "A new argument"
Dim new_bat As String = regex.Replace(batfile, "$1""" + new_argument + """ $2", 1)
It will now take everything between the first quote, and the next quote.
Instead of using Regex you could also read the lines with File.ReadAllLines(), take the desired line and split it with string.Split() and replace them in that way.
Something like:
string[] lines = File.ReadAllLines(fileName);
string commandLine = lines.Where(d => d.StartsWith("start")).Single();
string[] arguments = commandLine.Split(' ');
foreach (var argument in arguments)
{
if (argument.StartsWith("\""))
{
// do your stuff and reassemble
}
}

c# Replace backslash in string

I am reading the contents of an XLS file. Some older versions of excel add what I assume are escape sequences within the cell that causes me problems upon attempting to create a SQL column of that name.
Example string I have to work with is passed as
\0\0K\0\b\0Job
I would like to return this string as "Job". None of the replace sequences in the following job make a change and it returns as
\0\0K\0\b\0Job
C# does not allow that string to be created manually without escaping it with "\\", which defeats the purpose of what I need.
Any suggestions?
public static string CleanupHeaders(string _Col)
{
// Replace your #"\" parameter with double-escaped: #"\\"
_Col = _Col.Replace(#"\\0K", "");
_Col = _Col.Replace(#"\\b", "");
_Col = _Col.Replace(#"\\0", "");
return _Col;
}
Any suggestions?
I have one, since the string comes in as "\0\0K\0\b\0Job" your string replace methods _Col.Replace shouldn't need to use the literal syntax. In C# the \ is an escape character and the following characters create an escape sequence.
The issue is the verbatim string with the # syntax. Remove that and you get "Job". See this working .NET Fiddle - it has several demonstrations that will easily show you what happens. Take a look # MSDN's reference on string literals for more details.
public static string CleanupHeaders(string _Col)
{
_Col = _Col.Replace("\0K", "");
_Col = _Col.Replace("\b", "");
_Col = _Col.Replace("\0", "");
return _Col;
}
There should be no reason to use them in this situation.
Updated
The OP altered the question a little, so here's an update .NET Fiddle.
It's possible that the thing that's reporting the content of the string to you is reporting actual zero characters as \0 for human readability.
Try removing the #s from your replacement strings there.
The code that you provided should be working exactly as expected as seen in this example.
It's All In How It's Called
Since you mentioned that your initial string isn't being changed, it's worth noting that your replace function actually returns a string and doesn't perform an inline replacement, so you'll need to call it through :
// This will set your original string to the result of your CleanupHeaders() method
yourColumnVariable = CleanupHeaders(yourColumnVariable);
If you do want to perform an inline replacement of your existing string, simply update your CleanupHeaders() method to use a ref parameter to perform an update to the actual reference that was passed in :
// Notice the ref keyword
public static void CleanupHeaders(ref string _Col)
{
_Col = _Col.Replace(#"\0K", "");
_Col = _Col.Replace(#"\b", "");
_Col = _Col.Replace(#"\0", "");
}
and then you could simply call it using :
// This will update the yourColumnVariable to reflect any changes made in the method
CleanupHeaders(ref yourColumnVariable);
You can see an updated example that uses the ref approach here.
If you have a debugger, I would first of all suggest seeing what value the _Col string is when it's passed into your CleanupHeaders() method.
Depending where the string:
"\0\0K\0\b\0Job"
came from; I would imagine it is already escaped when it reaches your code.
The string would look something like this: "\\0\\0K\\0\\b\\0Job" when it reaches your method.
I would suggest 1 of 2 things:
1: Replace all your \ in the string with - or any character of your choice:
_Col = _Col.Replace(#"\\", "-");
And then replace your matching strings that now have the - prefix:
// Replace all your escaped backslashes
_Col = _Col.Replace(#"\\", "-");
// Now replace your new prefix + values you are looking to replace
_Col = _Col.Replace("-0K", "");
_Col = _Col.Replace("-0", "");
_Col = _Col.Replace("-b", "");
return _Col;
Or
2: \0 Is recognised as a character as it's escaped; so it's not being printed/output. Try changing your .Replace(#"\0", ""); with .Replace(#"\\0", ""); like so:
public static string CleanupHeaders(string _Col)
{
_Col = _Col.Replace(#"\\0K", ""); // Replaces the exact already escaped \\ value.
_Col = _Col.Replace(#"\\b", "");
_Col = _Col.Replace(#"\\0", "");
return _Col;
}

Splitting strings with slashes in C#

I have the following types of strings. One with three slashes and one with two:
a) filepath = "/F00C/Home/About"
b) filepath = "/Administration/Menus"
What I need to do is a function that will allow me to get the values of "home" and "administration" and put into topMenu variable and get the values of "Menus" and "About" and put this into the subMenu variable.
I am familiar with the function slashes = filePath.Split('/'); but my situation is not so simple as there are the two types of variables and in both cases I just need to get the last two words.
Is there a simple way that I could make the Split function work for both without anything to complex?
What's wrong with something like this ?
var splits = filePath.Split('/');
var secondLast = splits[splits.Length-2];
var last = splits[splits.Length-1];
Remarks:
Any check on the length of splits array (that must be >= 2) is missing.
Also, this code works only with forward-slash ('/'). To support both backslash and forward-slash separators, have a look at #Saeed's answer
Am I'm missing something or you just want:
var split = filepath.Split('/');
var last = split[split.Length -1];
var prev = split[split.Length -2];
var items = filePath.Split('/');
first = items[items.Length - 2];
second = items[items.Length - 1];
Also if this is a actual path you can use Path:
var dir = Path.GetDirectoryName(filePath);
dir = Path.GetFileName(dir);
var file = Path.GetFileName(filePath);
Edit: I edited Path version as the way discussed my digEmAll.

Categories

Resources