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#:需要将一个字符串拆分成一个字符串[],并在字符串的开头保留分隔符(也是一个字符串)的主要内容,如果未能解决你的问题,请参考以下文章

循环删除多条数据,先拼接字符串,再拆分成一个一个

将驼峰式句子拆分成单词

将 javascript 数组传递给 c# 方法

sql 表值函数-将一个传入的字符串用2中分隔符拆分成临时表

Python代码阅读(第25篇):将多行字符串拆分成列表

842. 将数组拆分成斐波那契序列