C#:需要将一个字符串拆分成一个字符串[],并在字符串的开头保留分隔符(也是一个字符串)
Posted
技术标签:
【中文标题】C#:需要将一个字符串拆分成一个字符串[],并在字符串的开头保留分隔符(也是一个字符串)【英文标题】:C#: Need to split a string into a string[] and keeping the delimiter (also a string) at the beginning of the string 【发布时间】:2021-01-31 00:02:22 【问题描述】:我觉得我太笨了,无法解决这个问题……
我有一些公式需要从一种语法“翻译”到另一种语法。 假设我有一个这样的公式(这是一个简单的公式,其他公式中有很多“天花板”):
string formulaString = "If([Param1] = 0, 1, Ceiling([Param2] / 0.55) * [Param3])";
我需要将“Ceiling()”替换为“Ceiling(;1)”(基本上,在“)”之前插入“;1”)。 我的尝试是在“Ceiling(”处拆分 fomulaString,这样我就可以遍历字符串数组并将字符串插入到正确的索引处(计算每个“(”和“)”以获得正确的索引)
到目前为止我所拥有的:
//splits correct, but loses "CEILING("
string[] parts = formulaString.Split(new[] "CEILING(" , StringSplitOptions.None);
//splits almost correct, "CEILING(" is in another group
string[] parts = Regex.Split(formulaString, @"(CEILING\()");
//splits almost every letter
string[] parts = Regex.Split(formulaString, @"(?=[(CEILING\()])");
当一切都完成后,我将字符串连接起来,这样我又得到了完整的公式。
我必须将什么设置为正则表达式模式才能实现此示例? (或任何其他对我有帮助的方法)
part1 = "If([Param1] = 0, 1, ";
part2 = "Ceiling([Param2] / 0.55) * [Param3])";
//part3 = next "CEILING(" in a longer formula and so on...
【问题讨论】:
你可以像这样使用String.Join(char separator, string[] value)
加入字符串:String.Join ("CEILING(", parts)
而不是连接它。
我有一些公式需要从一种语法“翻译”到另一种语法:根据转换的整体复杂性,可能值得一看 @ 987654322@.
对于语法更简单的语言,可能值得自己使用 Sprache 或 Pidgin 之类的东西构建解析器
你几乎明白了:(?=Ceiling)
在正则表达式中使用正前瞻零断言。 regular-expressions.info/lookaround.html
感谢所有评论员,我会进一步查看您提供给我的所有链接。由于语法翻译相对容易(只需在右括号前插入一些字符串),我将坚持使用 Regex.Split()
【参考方案1】:
正如我在评论中提到的,你几乎明白了:(?=Ceiling)
。不幸的是,这对于您的用例来说是不完整的。
我需要将“Ceiling()”替换为“Ceiling(;1)”(基本上,在“)”之前插入“;1”)。
这取决于你的正则表达式引擎(例如 JS):
string[] parts = Regex.Split(formulaString, @"(?<=Ceiling\([^)]*(?=\)))");
string modifiedFormula = String.join("; 1", parts);
正则表达式
(?<=Ceiling\([^)]*(?=\)))
(?<= ) Positive lookbehind
Ceiling\( Search for literal "Ceiling("
[^)] Match any char which is not ")" ..
* .. 0 or more times
(?=\)) Positive lookahead for ")", effectively making us stop before the ")"
这个正则表达式是一个零断言,因此不会丢失任何内容,它会在每个“Ceiling()”中的最后一个“)”之前切断你的字符串。
只要您嵌套了“Ceiling()”,此解决方案就会中断。那么您唯一的解决方案就是为 same reasons why you can't parse markup with regex 编写自己的解析器。
【讨论】:
非常感谢您的解释。我刚刚检查了大约 300 个必须翻译的公式,是的,有一些嵌套的“Ceiling()”。所以我必须为此编写一个解析器。【参考方案2】:Regex.Replace(formulaString, @"(?<=Ceiling\()(.*?)(?=\))","$1; 1");
注意:这不适用于嵌套的“天花板”,但它适用于Ceiling()
,它也不适用于Ceiling(AnotherFunc(x))
。为此,您需要以下内容:
Regex.Replace(formulaString, @"(?<=Ceiling\()((.*\((?>[^()]+|(?1))*\))*|[^\)]*)(\))","$1; 1$3");
但我无法让它与 .NET 一起使用,只能在 javascript 中使用。
【讨论】:
【参考方案3】:这是我的解决方案:
private string ConvertCeiling(string formula)
int ceilingsCount = formula.CountOccurences("Ceiling(");
int startIndex = 0;
int bracketCounter;
for (int i = 0; i < ceilingsCount; i++)
startIndex = formula.IndexOf("Ceiling(", startIndex);
bracketCounter = 0;
for (int j = 0; j < formula.Length; j++)
if (j < startIndex) continue;
var c = formula[j];
if (c == '(')
bracketCounter++;
if (c == ')')
bracketCounter--;
if (bracketCounter == 0)
// found end
formula = formula.Insert(j, "; 1");
startIndex++;
break;
return formula;
和CountOccurence:
public static int CountOccurences(this string value, string parameter)
int counter = 0;
int startIndex = 0;
int indexOfCeiling;
do
indexOfCeiling = value.IndexOf(parameter, startIndex);
if (indexOfCeiling < 0)
break;
else
startIndex = indexOfCeiling + 1;
counter++;
while (true);
return counter;
【讨论】:
以上是关于C#:需要将一个字符串拆分成一个字符串[],并在字符串的开头保留分隔符(也是一个字符串)的主要内容,如果未能解决你的问题,请参考以下文章