I have a string which contains various tags such as , I need to replace the entire matched string with the contents of the filename indicated, keeping in mind that the filename is not actually known so it cannot be directly searched for.
I get most of it, but what's hanging me up is how to use the subexpression outside a normal replace but instead as an argument to a method to return the passed files contents.
page= Regex.Replace(page,"<!--Include:(.*)-->",getFileContents($1));
The $1 is what's hanging me up because I cannot get the subexpression out like that.
Thanks in advance!
You can use the Regex.Replace's overload which takes MatchEvaluator
page= Regex.Replace(page,"<!--Include:(.*)-->",
m => getFileContents(m.Groups[1].Value));
Related
I've read the docs about the Directory.GetPath search pattern and how it is used, because I noticed that *.dll finds both test.dll and test.dll_20170206. That behavior is documented
Now, I have a program that lists files in a folder based on a user-configured mask and processes them. I noticed that masks like *.txt lead to the above mentioned "problem" as expected.
However, the mask fixedname.txt also causes fixedname.txt_20170206 or the like to appear in the list, even though the documentation states this only occurs
When you use the asterisk wildcard character in a searchPattern such as "*.txt"
Why is that?
PS: I just checked: Changing the file mask to fixednam?.txt does not help even though the docs say
When you use the question mark wildcard character, this method returns only files that match the specified file extension. For example, given two files, "file1.txt" and "file1.txtother", in a directory, a search pattern of "file?.txt" returns just the first file, whereas a search pattern of "file*.txt" returns both files.
If you need a solution you may transform the filter pattern into a regular expression by replacing * by (.*) and ? by .. You also have to escape some pattern characters like the dot. Then you check each filename you got from Directory.GetFiles against this regular expression. Keep in mind to not only check if it is a match but that the match length is equal to the length of the filename. Otherwise you get the same results as before.
GetFiles uses pattern serach, it searches for all names in path ending with the letters specified.
You can write code similar to below to get only .txt extension file
foreach (string strFileName in Directory.GetFiles(#"D:\\test\","*.txt"))
{
string extension;
extension = Path.GetExtension(strFileName);
if (extension != ".txt")
continue;
else
{
//processed the file
}
}
Background
I am trying to do some regex matching and replacing, but for some reason the replacement isn't correct in .NET.
Regex pattern - "^.*?/rebate/?$"
Input string - "/my-tax/rebate"
Replacement string - "/new-path/rebate"
Basically, if the word 'rebate' is seen in a string, the input string needs to be replaced entirely by the replacement string.
Problem
If I create a regex with the pattern and execute
patternMatch.Pattern.Replace("/my-tax/rebate", "/new-path/rebate")
I get /my-tax/new-path/rebate, which isn't correct.
But, if I execute -
new Regex(#"^.*?/rebate/?$").Replace("/my-tax/rebate", "/new-path/rebate"),
the result is correct - /new-path/rebate
Why is that?
patternMatch is an object with two properties - one Pattern (which is the Regex Pattern) and another one is TargetPath (which is the replacement string). In this example, I am only using the pattern property.
patternMatch.Pattern on debugging is
Here are the results during run time-
You are simply wrongly using the function. I'm not sure how you are getting /my-tax/new-path/rebate since it is giving me an error on ideone.com (Maybe you have a regex named Pattern?).
Anyway, you shouldn't have any issues with using the function like this:
patternMatch.Replace("/my-tax/rebate", "/new-path/rebate");
ideone demo
A number of points in your question are incorrect. The regex is replacing correctly.
Per #XiaoguangQiao's comment, what is patternMatch.Pattern.Replace? Your example...
var patternMatch = new Regex("^.*?/rebate/?$");
patternMatch.Pattern.Replace("/my-tax/rebate", "/new-path/rebate");
...errors with the message...
'System.Text.RegularExpressions.Regex' does not contain a definition for 'Pattern' and no extension method 'Pattern' accepting a first argument of type 'System.Text.RegularExpressions.Regex' could be found
...when I throw it into a quick LINQPad 4 query (set to C# Statement(s)).
pattern is a private string field of System.Text.RegularExpressions.Regex; and patternMatch.Replace("/my-tax/rebate", "/new-path/rebate") - which I expect is what you meant - yields the correct result ("/new-path/rebate") rather than the incorrect result you said you get ("/my-tax/new-path/rebate").
Otherwise your pattern(s) (i.e. with and without the extra / that #rene pointed out) is fine for the input ("/my-tax/rebate") and replacement ("/new-path/rebate") you initially outline - insofar as they match and yield the result you want. You can check this outside your code in quick fiddles with the extra / and without the extra /.
Use String.Replace Method.
str.replace("rebate","new-path/rebate")
http://msdn.microsoft.com/en-us/library/fk49wtc1%28v=vs.110%29.aspx
I don't have my code with me at home but I realized that I'll need to do a regex replace on a certain expression and I was wondering if there is a best practices for this.
What my code is currently doing is searching for matches in files, taking those matches out of a file(replacing them with ""), and then once all the files are processed I make a call to the .NET Process class to do some command line stuff. Specifically what i'll be doing is taking a group of files and copying them(merging)into one final output file. But there is the instance where every file to be merged has the exact same first line, which let's just say for the example is:
FIRST_NAME|MIDDLE_NAME|LAST_NAME|ADDRESS
Now, the first file having that is okay. And I figure that I'm going to do this final match and replace once the file is merged. But I only want to replace matches of that specific expression AFTER the first occurrence.
So, I read that C# has superb support for a Regex look behind? Would that be the proper way to implement "replacing matches after the first occurrence of a match" and if so how would you implement it given a sample regular expression?
My own personal solution to this was to return the amount of files in the folder with Directory.GetFiles and then in my foreach (string file in matches) I would declare a quick condition that says
if (count == directoryCount)
do not match and replace
count minus 1
elseif (count < directoryCount)
strip matching expression
and then every iteration through the foreach after the first run-through will strip out the matching expression from the file leaving only the first file with the expression I want to keep.
Thank you for any suggestions.
how about using replaceFirst() to backup the first occurency and mark it with some char. then use replaceAll(), and replaceFirst() again to roll back the first match.
Regex.Replace has a couple of overloads that provide for MatchEvaluator evaluator which is delegate on a Match returning the replacement String.
So you can use something like re.Replace(input, m => first ? (first=false, m.Value) : "") (but I've a VB programmer and have put this in without any syntax checking).
I have a data source that is comma-delimited, and quote-qualified. A CSV. However, the data source provider sometimes does some wonky things. I've compensated for all but one of them (we read in the file line-by-line, then write it back out after cleansing), and I'm looking to solve the last remaining problem when my regex-fu is pretty weak.
Matching a Quoted String inside of another Quoted String
So here is our example string...
"foobar", 356, "Lieu-dit "chez Métral", Chilly, FR", "-1,000.09", 467, "barfoo", 1,345,456,235,231, "935.18"
I am looking to match the substring "chez Métral", in order to replace it with the substring chez Métral. Ideally, in as few lines of code as possible. The final goal is to write the line back out (or return it as a method return value) with the replacement already done.
So our example string would end up as...
"foobar", 356, "Lieu-dit chez Métral, Chilly, FR", "-1,000.09", 467, "barfoo", 1,345,456,235,231, "935.18"
I know I could define a pattern such as (?<quotedstring>\"\w+[^,]+\") to match quoted strings, but my regex-fu is weak (database developer, almost never use C#), so I'm not sure how to match another quoted string within the named group quotedstring.
FYI: For those noticing the large integer that is formatted with commas but not quote-qualified, that's already handled. As is the random use of row-delimiters (sometimes CR, sometimes LF). As other problems...
Replace with this regex
(?<!,\s*|^)"([^",]*)"
now replace it with $1
try it here
escaping " with "" it would become
(?<!,\s*|^)""([^"",]*)""
I haven't been able to find anything online regarding this. There's RegexOptions, but it doesn't have Global as one of its options. The inline modifiers list also doesn't mention global matching.
In a nutshell, I've got a regex to parse something like
--arga= "arg1" --argb ="arg2"
into separate argument name/value pairs using this regex:
--(\\w+)\\s*=\\s*\"(\\w+)\"\\s*
but the .NET Regex class doesn't do it globally (iteratively). So in order for me to get this to work, I'd have to do a match, then remove this from the argument string, and loop over and over again until I've exhausted all of the arguments.
It would be nicer to run the regex once, and then loop over the match groups to get the name value pairs. Is this possible? What am I missing?
You're looking for the Regex.Matches method (plural), which returns a collection containing all of the matches in the original string.