Преобразование вкладок в пробелы в строке .NET

Я создаю текстовый синтаксический анализатор, используя регулярные выражения. Мне нужно преобразовать все символы табуляции в строку в пробелы. Я не могу предположить, сколько пространств вкладка должна включать в себя, иначе я мог бы заменить вкладку, скажем, на 4 пробела. Есть ли хорошее решение для этого типа проблемы. Мне нужно сделать это в коде, поэтому я не могу использовать внешний инструмент.


К сожалению, ни один из этих ответов не касается проблемы, с которой я столкнулся. Я извлекаю текст из внешних текстовых файлов, и я не могу предположить, как они были созданы или какая операционная система использовалась для их создания. Я считаю, что длина символа табуляции может варьироваться, поэтому, если я столкнулся с вкладкой, когда я читаю текстовый файл, я хочу знать, сколько пробелов мне нужно заменить.

Ответ 1

К сожалению, вы должны предположить, сколько пробелов представляет вкладка. Вам следует установить фиксированное значение (например, четыре) или сделать его пользовательским.

Самый быстрый способ сделать это -.NET (я использую С#):

var NewString = "This is a string with a    Tab";
var TabLength = 4;
var TabSpace = new String(' ', TabLength);

NewString = NewString.Replace("\t", TabSpace);

Затем вы можете изменить переменную TabLength на все, что вам нужно, обычно, как упоминалось ранее, на четыре пробела.

Вкладки во всех операционных системах одинаковой длины, одна вкладка! Отличается то, как программное обеспечение отображает их, обычно это эквивалентная ширина четырех пробелов, и это также предполагает, что на дисплее используется шрифт фиксированной ширины, например Courier New.

Например, моя IDE по выбору позволяет мне изменить ширину символа табуляции на значение, которое мне подходит.

Ответ 2

Я не уверен, как вкладки будут считываться из текстового файла Unix или независимо от ваших различных форматов, но это работает для встроенного текста. Возможно, это поможет.

var textWithTabs = "some\tvalues\tseperated\twith\ttabs";
var textWithSpaces = string.Empty;

var textValues = textWithTabs.Split('\t');

foreach (var val in textValues)
{
    textWithSpaces += val + new string(' ', 8 - val.Length % 8);
}

Console.WriteLine(textWithTabs);
Console.WriteLine(textWithSpaces);
Console.Read();

Ответ 3

Я думаю, что вы хотите сказать, что вы хотите заменить вкладки эффективным количеством пространств, в которые они были расширены. Первый способ, который приходит на ум, не предполагает регулярных выражений (и я не знаю, что эта проблема может быть решена с ними). ​​

  • Шаг через символ строки по символу, отслеживая текущую позицию в строке.
  • Когда вы найдете вкладку, замените ее на N пробелов, где N = tab_length - (current_position % tab_length).
  • Добавьте N в текущую позицию и продолжайте использовать строку.

Ответ 4

(Если вы ищете способ преобразования вкладок в пробелы в редакторе, см. в конце моего ответа.)

Недавно мне пришлось заменить вкладки пробелами.

Решение заменяет вкладку до 4 или 8 пробелов.

Логика перебирает входную строку по одному символу за раз и отслеживает текущую позицию (столбец #) в выходной строке.

  • Если он встречает \t (символ табуляции) - находит следующую позицию табуляции, вычисляет, сколько пробелов ему нужно, чтобы добраться до следующей позиции табуляции, и заменяет \t на это количество пробелов.
  • If \n (новая строка) - добавляет его к выходной строке и сбрасывает указатель положения на 1 в новой строке. Новые строки в Windows - \r\n, а в Unix (или разновидностях) - \n, поэтому я полагаю, что это должно работать на обеих платформах. Я тестировал на Windows, но у меня нет Unix под рукой.
  • Любые другие символы - добавляет его к выходной строке и увеличивает позицию.

.

using System.Text;

namespace CSharpScratchPad
{
    class TabToSpaceConvertor
    {
        static int GetNearestTabStop(int currentPosition, int tabLength)
        {
            // If already at the tab stop, jump to the next tab stop.
            if ((currentPosition % tabLength) == 1)
                currentPosition += tabLength;
            else
            {
                // If in the middle of two tab stops, move forward to the nearest.
                for (int i = 0; i < tabLength; i++, currentPosition++)
                    if ((currentPosition % tabLength) == 1)
                        break;
            }

            return currentPosition;
        }

        public static string Process(string input, int tabLength)
        {
            if (string.IsNullOrEmpty(input))
                return input;

            StringBuilder output = new StringBuilder();

            int positionInOutput = 1;
            foreach (var c in input)
            {
                switch (c)
                {
                    case '\t':
                        int spacesToAdd = GetNearestTabStop(positionInOutput, tabLength) - positionInOutput;
                        output.Append(new string(' ', spacesToAdd));
                        positionInOutput += spacesToAdd;
                        break;

                    case '\n':
                        output.Append(c);
                        positionInOutput = 1;
                        break;

                    default:
                        output.Append(c);
                        positionInOutput++;
                        break;
                }
            }
            return output.ToString();
        }
    }
}

Код вызова будет выглядеть так:

string input = "I\tlove\tYosemite\tNational\tPark\t\t,\t\t\tGrand Canyon,\n\t\tand\tZion";
string output = CSharpScratchPad.TabToSpaceConvertor.Process(input, 4);

Выходная строка получит значение:

    I   love    Yosemite    National    Park        ,           Grand Canyon,
            and Zion

Как преобразовать вкладки в пробелы в редакторе?

Если вы наткнулись на этот вопрос, потому что вы не смогли найти возможность конвертировать вкладки в пробелы в редакторах (так же, как я и думал написать свою собственную утилиту для этого), вот где эта опция находится в разных редакторах -

Notepad++:              Edit → Blank Operations → TAB to Space
Visual Studio:          Edit → Advanced → Untabify Selected Lines
SQL Management Studio:  Edit → Advanced → Untabify Selected Lines

Ответ 5

Это именно то, что они говорят о необходимости. Я написал это в Visual Basic 6.0. Я сделал несколько быстрых обновлений VB.NET 2010, но он мог бы использовать некоторые улучшения для него. Просто убедитесь и установите нужную ширину закладки; он установил там 8. Просто отправьте строку или исправьте ее прямо в текстовом поле:

RichTextBox1.Text = strFixTab(RichTextBox1.Text)

Function strFixTab(ByVal TheStr As String) As String
    Dim c As Integer
    Dim i As Integer
    Dim T As Integer
    Dim RetStr As String
    Dim ch As String
    Dim TabWidth as Integer = 8    ' Set the desired tab width

    c = 1
    For i = 1 To TheStr.Length
        ch = Mid(TheStr, i, 1)
        If ch = vbTab Then
            T = (TabWidth + 1) - (c Mod TabWidth)
            If T = TabWidth + 1 Then T = 1
            RetStr &= Space(T)
            c += T - 1
        Else
            RetStr &= ch
        End If
        If ch = vbCr Or ch = vbLf Then
            c = 1
        Else
            c += 1
        End If
    Next
    Return RetStr
End Function

Ответ 6

Вы можете использовать функцию замены:

char tabs = '\u0009';
String newLine = withTabs.Replace(tabs.ToString(), "    ");

Ответ 7

Я не уверен, что мое решение более эффективно в исполнении, но оно более компактно в коде. Это близко к решению пользователя ckal, но собирает разделенные строки, используя функцию Join, а не '+ ='.

public static string ExpandTabs(string input, int tabLength)
{
    string[] parts = input.Split('\t');
    int count = 0;
    int maxpart = parts.Count() - 1;
    foreach (string part in parts)
    {
        if (count < maxpart)
            parts[count] = part + new string(' ', tabLength - (part.Length % tabLength));
        count++;
    }
    return(string.Join("", parts));
}

Ответ 8

Многие ответы здесь не учитывают, что табуляция означает количество пробелов до следующей табуляции, а не "четыре (или восемь) пробелы". Многие ответы также не учитывают возврат каретки и перевод строки, поэтому не обрабатывают многострочный контент. Так что без лишних слов:

    public static string TabsToSpaces(string inTxt, int tabLen=4 )
    {
        var outTxt = new List<string>();

        var textValues = inTxt.Split('\t');

        foreach (var val in textValues)
        {
            var lines = val.Split("\r");
            var preTxt = lines[lines.Length - 1];
            preTxt = preTxt.Replace("\n", "");
            var numSpaces = tabLen - preTxt.Length % tabLen;
            if (numSpaces == 0)
                numSpaces = tabLen;
            outTxt.Add(val + new string(' ', numSpaces));
        }
        return String.Join("", outTxt);
    }

(Кстати, это также эффективно для процессора, так как не переписывает гигантские строки.)

Ответ 9

Вы хотите, чтобы конвертировать вкладку в N пробелов? Один быстрый и грязный вариант:

output = input.Replace("\t", "".PadRight(N, (char)" "));

Очевидно, что N должно быть определено где-то, будь то пользовательский ввод или в другом месте программы.

Ответ 10

Regex.Replace(input, "\t", "    ");

Ответ 11

Я не совсем уверен, что вы подразумеваете под "Я не могу предположить, сколько пробелов должна включать вкладка", но этот пример заменит вкладки на любое количество пробелов, которые вы указали.

public static string ReplaceTabs(string value, int numSpaces)
{
   string spaces = new String(' ', numSpaces);
   return value.Replace("\t", spaces);     
}

Ответ 12

Я думаю, что все рассмотрели это, но символ табуляции - только это. Один персонаж... Символ представлен \t. Каждое приложение может выбрать для отображения один пробел, два пробела, четыре пробела, смайлик. Как бы то ни было... Так что... реального ответа на это нет.