我有以下字符串
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)类型时。
请帮忙
答案 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也可以提供帮助。最简单的解析器是递归的。这样你可以肯定
具有错误检查功能的好解析器就像为您指定特定语言的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;
}
}
}
}