2009-02-03 84 views
11

我正在使用正則表達式構建文本解析器。我需要將字符串中的所有制表符轉換爲空格字符。我不能假定標籤應該包含多少空格,否則我可以用4個空格字符替換標籤。這種類型的問題有什麼好的解決方案嗎?我需要在代碼中這樣做,所以我不能使用外部工具。將製表符轉換爲.NET字符串中的空格


不幸的是,這些答案都沒有解決我遇到的問題。我從外部文本文件中提取文本,我不能假設它們是如何創建的,或者使用哪個操作系統來創建它們。我相信製表符的長度可能會有所不同,所以如果我在閱讀文本文件時遇到選項卡,我想知道應該用多少個空格字符替換它。

+2

這裏有些答案是不知道標籤的概念停止(請參閱http ://www.gnu.org/software/emacs/manual/html_node/emacs/Tab-Stops.html和http://www.jwz.org/doc/tabs-vs-spaces.html)。 @ckal,Nick-McCowin和user275640是正確的答案。 – Jonke 2013-11-14 08:24:35

+0

@Jonke發佈了一個新的解決方案,以最多4或8個空格正確確定製表符。 – HappyTown 2017-01-31 17:00:50

回答

0

可以使用替換功能:

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

聽起來像他希望結果仍然在製表位上排隊 – 2009-02-03 17:38:04

+0

不起作用,因爲它沒有考慮到還沒有製表符對齊的製表符(請參閱@HappyTown答案)。假設4「aa \ tb」的標籤寬度變成「aab」而不是「aa__b」。 – Sprotty 2017-02-09 13:38:19

-1

您希望能夠將標籤轉換爲n個空格?一個快速和骯髒的選項是:

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

顯然N必須定義某處,無論是用戶輸入或程序中的其他地方。

-1
Regex.Replace(input,"\t"," "); 
+0

不起作用,因爲它沒有考慮沒有製表符對齊的選項卡(請參閱@HappyTown答案)。 – Sprotty 2017-02-09 13:36:39

15

不幸的是,你需要假設一個標籤代表多少個空格。您應該將其設置爲固定值(如提到的四個值)或將其設置爲用戶選項。

做到這一點,最快捷的方法是.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 of choice允許我將製表符的寬度更改爲適合我的值。

+2

Tabs佔用TabSpace字符,並不是那麼多字符。 – 2009-02-03 17:39:05

+0

@JoelCoehoorn發佈了一個新的解決方案,以最多4或8個空格正確確定製表符。 – HappyTown 2017-01-31 17:01:14

-1

我不太確定你的意思是「我不能假定標籤應該包含多少個空格」,但是這個例子將用你指定的任意數量的空格替換標籤。

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

我想你的意思是說,你想用它們擴展到的有效數量的空格替換標籤。首先想到的方式不涉及正則表達式(我不知道這個問題可以通過它們來解決)。

  • 逐字符逐字符串,跟蹤字符串中當前位置。
  • 當您找到選項卡時,請將其替換爲N個空格,其中N = tab_length - (current_position % tab_length)
  • 將N添加到當前位置,然後通過字符串繼續。
6

我不確定標籤是如何從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(); 
-1

我想每個人都已經說過了,但製表符就是這樣。一個字符..字符用\ t表示。每個應用程序都可以選擇用一個空格,兩個空格,4個空格,一個笑臉......任意......來顯示它,所以沒有真正的答案。

1

這正是他們正在談論的需要。我在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 
1

(如果你正在尋找如何將製表符轉換爲空格在編輯器中,看到我的回答結束)

幾乎8歲的問題,但我最近需要用空格替換標籤。

該解決方案替換選項卡高達 4或8個空格。

邏輯通過輸入字符串迭代一次一個字符,並跟蹤輸出字符串中的當前位置(列#)。

  • 如果遇到\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 
0

我不確定我的解決方案是否更有效執行,但代碼更緊湊。這與@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

相當放在這裏忽視標籤意味着的空間到下一個標籤的數量停止,而不是「四(或八)空間」幾個答案。不少答案也忽略了回車和換行,因此不處理多行內容。因此,事不宜遲:

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

(順便說一句,這也是CPU在高效率不會重新複製巨字符串)

相關問題