Reputation: 95
I need to replace all commas outside parentheses and quotes
To replace only considering the parentheses I have the following REGEX
,(?![^(]*\))
I made the following REGEX that select the things inside parentheses and quotes in one group and the commas outside parentheses in another group, but I didn't find a simple way to replace the strings only for one group
((?:\((?>[^()]|)*\)|'(?>[^']|)*'))|(,)
Example: What I want is to put this input
ISNULL(d.Type, 0), d.Subject + ', ' + d.Name, d.Something,array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field), test
and have this result
ISNULL(d.Type, 0) DESC, d.Subject + ', ' + d.Name DESC, d.Something DESC,array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field) DESC, test
Upvotes: 2
Views: 361
Reputation: 626802
You can use
Regex.Replace(text, @"(\([^()]*\)|'[^']*')|\s*,", m =>
m.Groups[1].Success ? m.Value : " DESC,")
Details:
(
- Group 1 start (the capturing group is necessary to restore the match later in the resulting string):
\([^()]*\)
- a (
char, then any zero or more chars other than (
and )
and then a )
char|
- or
'[^']*'
- '
, zero or more chars other than '
, and a '
char)
- end of the capturing group|
- or\s*,
- zero or more whitespaces and then a ,
char.See the C# demo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
var text = "ISNULL(d.Type, 0), d.Subject + ', ' + d.Name, d.Something,array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field), test";
var pattern = @"(\([^()]*\)|'[^']*')|\s*,";
var result = Regex.Replace(text, pattern, m => m.Groups[1].Success ? m.Value : " DESC,");
Console.WriteLine(result);
}
}
Output:
ISNULL(d.Type, 0) DESC, d.Subject + ', ' + d.Name DESC, d.Something DESC,array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field) DESC, test
Upvotes: 3
Reputation: 186678
I doubt if Regex
is a good tool for the task: what if you have parentheses within quote?
abc + '(' + def, pqr + ')'
you want a simple, but parser. Let's implement it as a Finite State Machine:
private static string MyReplace(string value) {
if (string.IsNullOrEmpty(value))
return value;
StringBuilder sb = new StringBuilder(value.Length * 2);
// if we are within quotation
bool inQuot = false;
// if we are within parenthesis (note, they can be nested)
int parenthesis = 0;
foreach (char c in value) {
if (c == ',' && !inQuot && parenthesis == 0)
sb.Append(" DESC,");
else
sb.Append(c);
// Possible states changing
if (c == '\'')
inQuot = !inQuot;
if (!inQuot && c == '(')
parenthesis += 1;
if (!inQuot && c == ')')
parenthesis -= 1;
}
return sb.ToString();
}
Upvotes: 2
Reputation: 74605
I think I'd just have a simple state machine style interpretation..
bool inBra = false;
bool inQuo = false;
var sb = new StringBuilder();
foreach(char c in str){
if(c == '(')
inBra = true;
if(c == ')')
inBra = false;
if(c == '\'')
inQuo = !inQuo;
if(c == ',' && !inBra && !inQuo)
sb.Append(" DESC,");
else
sb.Append(c);
}
You could handle nesting by making the bool an int that you ++ and --, and only DESC when it's 0
Upvotes: 2