.NET中的String Splitter

时间:2010-08-25 12:28:11

标签: c# .net

我有以下字符串

P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO

我需要输出

P

MV

A1ZWR

MAV#(X,,)

PV

MOV#(X,12,33)

LO

可以看出,通过“,”拆分可以轻松完成,但问题来了

当它是MAV#(X ,,)或MOV#(X,12,33)类型时。

请帮忙

10 个答案:

答案 0 :(得分:8)

您可以使用正则表达式匹配分隔符之间的值,并指定parantheses中的所有内容都是值的一部分。例如:

string data = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO";

foreach (Match m in Regex.Matches(data, @"\s*((\(.*?\)|[^,])*)(,|$)")) {
  Console.WriteLine(m.Groups[1].Value);
}

输出:

P
MV
A1ZWR
MAV#(X,,)
PV
MOV#(X,12,33)
LO

答案 1 :(得分:4)

string input = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO";
IList<string> parts = new List<string>();
int paranthesisCount = 0;
int lastSplitIndex = 0;
for (int i = 0; i < input.Length; i++)
{
    if (input[i] == '(')
    {
        paranthesisCount++;
        continue;
    }
    if (input[i] == ')')
    {
        paranthesisCount--;
        continue;
    }
    if (input[i] == ',' && paranthesisCount == 0)
    {
        parts.Add(input.Substring(lastSplitIndex, i - lastSplitIndex));
        lastSplitIndex = i + 1;
    }
}
if (input.Length - lastSplitIndex > 0)
{
    parts.Add(input.Substring(lastSplitIndex, input.Length - lastSplitIndex));
}

答案 2 :(得分:4)

由于没有这样的解决方案只使用LINQ,我感兴趣的是它看起来我想出了这个。但我不建议在生产代码中使用它。实际上我希望它更好,但由于需要处理嵌套的parenthenses,我必须引入可变状态变量。

string data = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO";

int depth = 0;
int group = 0;

var result = data
    .GroupBy(x => { 
        if (x == '(') depth++;
        if (x == ')') depth--;
        if (x == ',' && depth == 0) group++; 
        return group; })
    .Select(x => new String(x.ToArray()).Trim(' ', ','))

答案 3 :(得分:2)

最好的办法是为数据编写解析器。查找CSV解析库,您可以修改一个以支持#(...)而不是"...",而不会有太多困难。

答案 4 :(得分:1)

如何循环和检测商标字符,例如()

string[] test = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO".Split(',');

bool insideElement = false;
string insideElementResult = "";
List<string> result = new List<string>();
foreach (string s in test)
{
    //Determine context:
    if (s.IndexOf("(") > -1)
        insideElement = true;

    //Determine where to add my nice string
    if (!insideElement)
        result.Add(s);
    else
        insideElementResult += s;

    //Determine if contact has ended:
    if (s.IndexOf(")") > -1)
    {
        insideElement = false;
        result.Add(insideElementResult);
        insideElementResult = null;
    }
    else if (insideElement)
    {
        insideElementResult += ",";
    }

}

结果:

    [0] "P" string
    [1] "MV"    string
    [2] "A1ZWR" string
    [3] "MAV#(X,,)" string
    [4] " PV"   string
    [5] "MOV#(X,12,33)" string
    [6] "LO"    string

当然,不像正则表达式那样花哨,并且会在内括号上打破,但是嘿,它有效;)

答案 5 :(得分:1)

要理解字符串,Parser也可以提供帮助。最简单的解析器是递归的。这样你可以肯定

  1. 所有括号都没问题
  2. 没有错误的分裂出现
  3. 所有令牌都是正确的(可能有所帮助,但取决于申请)
  4. 具有错误检查功能的好解析器就像为您指定特定语言的xsd。

    我用ANTLR完成了一个解析器。看看它是否对你有所帮助。这可能是一个过度杀伤问题。试想一下。

答案 6 :(得分:0)

使用不属于您的参赛作品的分隔符。

 P~MV~A1ZWR~MAV#(X,,)~ PV~MOV#(X,12,33)~LO

甚至是一个不可见的字符(0x00?)

答案 7 :(得分:0)

如果这是您正在填充的文件,请使用不会出现问题的分隔符,例如|例如。如果它是您正在扫描和解析的文件,您可以使用正则表达式来提取所需的数据。

如果没有,您可能必须拆分字符串并查看存储桶,同时查找问题并进行任何必要的合并和进一步拆分。

答案 8 :(得分:0)

这个函数将拉出所有标记,确保标记之间没有双重逗号,并确保所有括号都已关闭。这有点长。

IEnumerable<string> Tokenise(string input)
{
    const char tokenlimiter = ',';
    const char funcstart = '#';
    const char funcend = ')';
    StringBuilder token = new StringBuilder(5);
    bool gotfunc = false;
    bool gotone = false;
    int pos = 0;
    int opened = 0;
    foreach(char c in input)
    {
        if (c == funcstart)
        {
            gotfunc = true;
            opened++;
        }
        if(c == funcend)
        {
            gotfunc = false;
            opened--;
        }
        if(!gotfunc && c == tokenlimiter)
        {
            gotone = true;
            if(token.Length == 0)
            {
                throw new ArgumentException("Blank instruction at " + pos, input);
            }
            yield return token.ToString();
        }
        if(gotone)
        {
            token = new StringBuilder(5);
            gotone = false;
        }
        else
        {
            token.Append(c);    
        }
        if(pos == input.Length - 1)
        {
            if (!gotfunc && opened == 0 && c != tokenlimiter)
            {
                yield return token.ToString();
            }
            else if (gotfunc || opened != 0)
            {
                throw new ArgumentException("Broken function", input);
            }
            else
            {
                throw new ArgumentException("Blank instruction at " + pos, input);
            }
        }
        pos++;
    }

}

答案 9 :(得分:0)

private static void CreateListString(string s)
{
string[] splits = s.Split(new char[] { ',' });
List<string> strs = new List<string>();
bool isLimiterSeen = false;
StringBuilder str = null;
for (int i = 0; i < splits.Length; i++)
{
if (splits[i].Contains("#("))
{
isLimiterSeen = true;
str = new StringBuilder();
}
if (!isLimiterSeen)
strs.Add(splits[i]);
else
{
str = str.Append("," + splits[i]);
if (splits[i].EndsWith(")"))
{
if (str.ToString().StartsWith(","))
strs.Add(str.ToString().Substring(1));
else
strs.Add(str.ToString());
isLimiterSeen = false;
str = null;
}
}
}
}