简体   繁体   English

缩进多行文本

[英]Indent multiple lines of text

I need to indent multiple lines of text (in contrast to this question for a single line of text ).我需要缩进多行文本(与此问题的单行文本相反)。

Let's say this is my input text:假设这是我的输入文本:

First line
  Second line
Last line

What I need is this result:我需要的是这个结果:

    First line
      Second line
    Last line

Notice the indentation in each line.注意每一行的缩进。

This is what I have so far:这是我到目前为止:

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();

Is there a safer/simpler way to do it?有没有更安全/更简单的方法来做到这一点?

My concern is in the split method, which might be tricky if text from Linux, Mac or Windows is transfered, and new lines might not get splitted correctly in the target machine.我担心的是拆分方法,如果传输来自 Linux、Mac 或 Windows 的文本,这可能会很棘手,并且新行可能无法在目标机器中正确拆分。

Since you are indenting all the lines, how about doing something like:既然您要缩进所有行,那么做以下事情如何:

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

Which should cover both Windows \\r\\n and Unix \\n end of lines.这应该涵盖 Windows \\r\\n 和 Unix \\n 行尾。

Just replace your newline with newline + indent:只需用换行符 + 缩进替换换行符:

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

The following solution may seem long-winded compared to other solutions posted here;与此处发布的其他解决方案相比,以下解决方案可能显得冗长; but it has a few distinct advantages:但它有几个明显的优点:

  • It will preserve line separators / terminators exactly as they are in the input string.它将完全保留输入字符串中的行分隔符/终止符。
  • It will not append superfluous indentation characters at the end of the string.它不会在字符串末尾附加多余的缩进字符。
  • It might run faster, as it uses only very primitive operations (character comparisons and copying; no substring searches, nor regular expressions).可能运行得更快,因为它只使用非常原始的操作(字符比较和复制;没有子字符串搜索,也没有正则表达式)。 (But that's just my expectation; I haven't actually measured.) (但这只是我的期望;我还没有实际测量过。)
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's answer got me thinking about not appending superfluous indentation characters. Stakx 的回答让我开始考虑不附加多余的缩进字符。 And I think is best to avoid those characters not only at the end, but also in the middle and beginning of the string (when that's all that line has).我认为最好避免这些字符,不仅在末尾,而且在字符串的中间和开头(当这就是该行的全部内容时)。

I used a Regex to replace new lines only if they are not followed by another new line, and another Regex to avoid adding the first indent in case the string begins with a new line:我使用正则表达式替换新行,仅当它们后面没有另一个新行时,另一个正则表达式来避免在字符串以新行开头的情况下添加第一个缩进:

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);
}

I create the Regex s outside the method in order to speed up multiple replacements.我创建为了加快多替换正则表达式外面的方法。

This solution can be tested at: https://ideone.com/9yu5Ih此解决方案可以在以下位置进行测试: https : //ideone.com/9yu5Ih

If you need a string extension that adds a generic indent to a multi line string you can use:如果您需要一个向多行字符串添加通用缩进的字符串扩展,您可以使用:

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));
}

This extension skips empty lines.此扩展跳过空行。 This solution is really simple to understand if you know linq and it's more simple to debug and change if you need to adapt it to different scopes.如果您了解 linq,则此解决方案非常容易理解,如果您需要使其适应不同的范围,则调试和更改会更简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM