.net C#中逐字字符串的多行格式(前缀为@)

67up9zun  于 2023-05-02  发布在  .NET
关注(0)|答案(5)|浏览(194)

我喜欢在c#中使用@“字符串”,尤其是当我有很多多行文本的时候。唯一的烦恼是我的代码格式在这样做时变得乱七八糟,因为第二行和更大的行被完全推到了左边,而不是使用我格式精美的代码的缩进。我知道这是设计好的,但是有没有什么方法可以让这些行缩进,而不需要在输出中添加实际的制表符/空格?
添加示例:

var MyString = @" this is 
a multi-line string
in c#.";

我的变量声明缩进到了“正确”的深度,但是字符串中的第二行和后面的行被推到了左边距--所以代码有点难看。您可以在第2行和第3行的开头添加制表符,但字符串本身将包含这些制表符。有意义吗

t1rydlwq

t1rydlwq1#

字符串扩展怎么样?更新:我重读了你的问题,我希望有一个更好的答案。这也是困扰我的事情,必须像下面这样解决它是令人沮丧的,但从好的方面来说,它确实起作用。

using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    public static class StringExtensions
    {
        public static string StripLeadingWhitespace(this string s)
        {
            Regex r = new Regex(@"^\s+", RegexOptions.Multiline);
            return r.Replace(s, string.Empty);
        }
    }
}

和一个示例控制台程序:

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string x = @"This is a test
                of the emergency
                broadcasting system.";

            Console.WriteLine(x);

            Console.WriteLine();
            Console.WriteLine("---");
            Console.WriteLine();

            Console.WriteLine(x.StripLeadingWhitespace());

            Console.ReadKey();
        }
    }
}

和输出:

This is a test
                of the emergency
                broadcasting system.

---

This is a test
of the emergency
broadcasting system.

如果你决定走这条路,一个更干净的方法来使用它:

string x = @"This is a test
    of the emergency
    broadcasting system.".StripLeadingWhitespace();
// consider renaming extension to say TrimIndent() or similar if used this way
8ljdwjyq

8ljdwjyq2#

Cymen给出了正确的解决方案。我使用的方法与Scala的stripMargin()方法类似。下面是我的扩展方法的样子:

public static string StripMargin(this string s)
{
    return Regex.Replace(s, @"[ \t]+\|", string.Empty);
}
  • 用途:*
var mystring = @"
        |SELECT 
        |    *
        |FROM
        |    SomeTable
        |WHERE
        |    SomeColumn IS NOT NULL"
    .StripMargin();
  • 结果:*
SELECT 
    *
FROM
    SomeTable
WHERE
    SomeColumn IS NOT NULL
dly7yett

dly7yett3#

我想不出一个能完全满足你的问题的答案,但是你可以写一个函数,从字符串中包含的文本行中去掉前导空格,并在每次创建这样的字符串时调用它。

var myString = TrimLeadingSpacesOfLines(@" this is a 
    a multi-line string
    in c#.");

是的,这是一个黑客,但你指定你接受黑客在你的问题。

cld4siwp

cld4siwp4#

这里有一个较长的解决方案,它试图尽可能地模仿textwrap.dedent。第一行保持原样,预计不会缩进。(您可以使用doctest-csharp基于doctests生成单元测试。)

/// <summary>
/// Imitates the Python's
/// <a href="https://docs.python.org/3/library/textwrap.html#textwrap.dedent">
/// <c>textwrap.dedent</c></a>.
/// </summary>
/// <param name="text">Text to be dedented</param>
/// <returns>array of dedented lines</returns>
/// <code doctest="true">
/// Assert.That(Dedent(""), Is.EquivalentTo(new[] {""}));
/// Assert.That(Dedent("test me"), Is.EquivalentTo(new[] {"test me"}));
/// Assert.That(Dedent("test\nme"), Is.EquivalentTo(new[] {"test", "me"}));
/// Assert.That(Dedent("test\n  me"), Is.EquivalentTo(new[] {"test", "  me"}));
/// Assert.That(Dedent("test\n  me\n    again"), Is.EquivalentTo(new[] {"test", "me", "  again"}));
/// Assert.That(Dedent("  test\n  me\n    again"), Is.EquivalentTo(new[] {"  test", "me", "  again"}));
/// </code>
private static string[] Dedent(string text)
{
    var lines = text.Split(
        new[] {"\r\n", "\r", "\n"},
        StringSplitOptions.None);

    // Search for the first non-empty line starting from the second line.
    // The first line is not expected to be indented.
    var firstNonemptyLine = -1;
    for (var i = 1; i < lines.Length; i++)
    {
        if (lines[i].Length == 0) continue;

        firstNonemptyLine = i;
        break;
    }

    if (firstNonemptyLine < 0) return lines;

    // Search for the second non-empty line.
    // If there is no second non-empty line, we can return immediately as we
    // can not pin the indent.
    var secondNonemptyLine = -1;
    for (var i = firstNonemptyLine + 1; i < lines.Length; i++)
    {
        if (lines[i].Length == 0) continue;

        secondNonemptyLine = i;
        break;
    }

    if (secondNonemptyLine < 0) return lines;

    // Match the common prefix with at least two non-empty lines
    
    var firstNonemptyLineLength = lines[firstNonemptyLine].Length;
    var prefixLength = 0;
    
    for (int column = 0; column < firstNonemptyLineLength; column++)
    {
        char c = lines[firstNonemptyLine][column];
        if (c != ' ' && c != '\t') break;
        
        bool matched = true;
        for (int lineIdx = firstNonemptyLine + 1; lineIdx < lines.Length; 
                lineIdx++)
        {
            if (lines[lineIdx].Length == 0) continue;
            
            if (lines[lineIdx].Length < column + 1)
            {
                matched = false;
                break;
            }

            if (lines[lineIdx][column] != c)
            {
                matched = false;
                break;
            }
        }

        if (!matched) break;
        
        prefixLength++;
    }

    if (prefixLength == 0) return lines;
    
    for (var i = 1; i < lines.Length; i++)
    {
        if (lines[i].Length > 0) lines[i] = lines[i].Substring(prefixLength);
    }

    return lines;
}
wz3gfoph

wz3gfoph5#

在C# 11中,你现在可以使用原始字符串。

var MyString = """
    this is 
    a multi-line string
    in c#.
    """;

输出为:

this is
a multi-line string
in c#.

它还结合了字符串插值:

var variable = 24.3;
var myString = $"""
    this is 
    a multi-line string
    in c# with a {variable}.
    """;

相关问题