Преобразование табуляции в пробелы в строке .NET - PullRequest
11 голосов
/ 03 февраля 2009

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

<Ч />

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

Ответы [ 12 ]

16 голосов
/ 03 февраля 2009

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

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

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 по выбору позволяет мне изменить ширину символа табуляции на значение, которое мне подходит.

6 голосов
/ 03 февраля 2009

Я не уверен, как вкладки будут читать из текстового файла 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 голосов
/ 31 января 2017

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

Почти 8-летний вопрос, но недавно мне потребовалось заменить символы табуляции пробелами.

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

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

  • Если встречается \t (символ табуляции) - Находит следующую позицию табуляции, вычисляет, сколько пробелов нужно получить до следующей остановки табуляции, заменяет \ t на это количество пробелов.
  • Если \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
3 голосов
/ 03 февраля 2009

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

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

Это именно то, о чем они говорят. Я написал это еще в 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
0 голосов
/ 26 ноября 2017

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

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

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

0 голосов
/ 03 августа 2017

Я не уверен, что мое решение более эффективно в исполнении, но оно более компактно в коде. Это близко к решению @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));
}
0 голосов
/ 03 февраля 2009

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

0 голосов
/ 03 февраля 2009

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

public static string ReplaceTabs(string value, int numSpaces)
{
   string spaces = new String(' ', numSpaces);
   return value.Replace("\t", spaces);     
}
0 голосов
/ 03 февраля 2009
Regex.Replace(input,"\t","    ");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...