缩进多行文本

本文关键字:文本 缩进 | 更新日期: 2023-09-27 17:56:39

>我需要缩进多行文本(与单行文本的这个问题相反)。

假设这是我的输入文本:

First line
  Second line
Last line

我需要的是这个结果:

    First line
      Second line
    Last line

请注意每行中的缩进。

这是我到目前为止所拥有的:

var textToIndent = @"First line
  Second line
Last line.";
var splittedText = textToIndent.Split(new string[] {Environment.NewLine}, StringSplitOptions.None);
var indentAmount = 4;
var indent = new string(' ', indentAmount);
var sb = new StringBuilder();
foreach (var line in splittedText) {
    sb.Append(indent);
    sb.AppendLine(line);
}
var result = sb.ToString();

有没有更安全/更简单的方法?

我担心的是拆分方法,如果传输来自 Linux、Mac 或 Windows 的文本,并且新行可能无法在目标机器中正确拆分,这可能会很棘手。

缩进多行文本

既然你缩进了所有的行,那么做一些事情怎么样:

var result = indent + textToIndent.Replace("'n", "'n" + indent);

这应该涵盖 Windows ''r' 和 Unix ' 行尾。

只需将换行符替换为换行符 + 缩进:

var indentAmount = 4;
var indent = new string(' ', indentAmount);
textToIndent = indent + textToIndent.Replace(Environment.NewLine, Environment.NewLine + indent);

与此处发布的其他解决方案相比,以下解决方案可能看起来很冗长;但它有几个明显的优势:

  • 它将完全保留输入字符串中的行分隔符/终止符。
  • 它不会在字符串末尾附加多余的缩进字符。
  • 它可能运行得更快,因为它只使用非常原始的操作(字符比较和复制;没有子字符串搜索,也没有正则表达式)。(但这只是我的期望;我实际上还没有测量过。
static string Indent(this string str, int count = 1, char indentChar = ' ')
{
    var indented = new StringBuilder();
    var i = 0;
    while (i < str.Length)
    {
        indented.Append(indentChar, count);
        var j = str.IndexOf(''n', i + 1);
        if (j > i)
        {
            indented.Append(str, i, j - i + 1);
            i = j + 1;
        }
        else
        {
            break;
        }
    }
    indented.Append(str, i, str.Length - i);
    return indented.ToString();
}

Stakx的回答让我想到不要附加多余的缩进字符。我认为最好不仅在末尾,而且在字符串的中间和开头(当这就是该行的全部内容时)避免这些字符。

我使用正则表达式来替换新行,仅当它们后面没有另一个新行时,另一个正则表达式以避免在字符串以新行开头的情况下添加第一个缩进:

Regex regexForReplace = new Regex(@"('n)(?!['r'n])");
Regex regexForFirst = new Regex(@"^(['r'n]|$)");
string Indent(string textToIndent, int indentAmount = 1, char indentChar = ' ')
{
    var indent = new string(indentChar, indentAmount);
    string firstIndent = regexForFirst.Match(textToIndent).Success ? "" : indent;
    return firstIndent + regexForReplace.Replace(textToIndent, @"$1" + indent);
}

我在方法外部创建正则表达式以加快多次替换。

此解决方案可在以下位置进行测试: https://ideone.com/9yu5Ih

如果需要向多行字符串添加泛型缩进的字符串扩展名,则可以使用:

public static string Indent(this string input, string indent)
{
    return string.Join(Environment.NewLine, input.Split(Environment.NewLine).Select(item => string.IsNullOrEmpty(item.Trim()) ? item : indent + item));
}

此扩展跳过空行。如果您了解 linq,则此解决方案非常易于理解,如果需要使其适应不同的范围,则调试和更改会更加简单。