2009-02-03 14 views
11

Estoy construyendo un analizador de texto usando expresiones regulares. Necesito convertir todos los caracteres de tabulación en una cadena para espaciar los caracteres. No puedo suponer cuántos espacios debe abarcar una pestaña, de lo contrario podría reemplazar una pestaña con, por ejemplo, 4 espacios. ¿Hay alguna buena solución para este tipo de problema? Necesito hacer esto en código así que no puedo usar una herramienta externa.Convierte pestañas a espacios en una cadena .NET


Lamentablemente, ninguna de estas respuestas resuelve el problema que me plantea. Estoy extrayendo texto de archivos de texto externos y no puedo suponer cómo fueron creados o qué sistema operativo se utilizó para crearlos. Creo que la longitud del carácter de la pestaña puede variar, por lo que si encuentro una pestaña cuando estoy leyendo el archivo de texto, quiero saber con cuántos espacios debo reemplazarlo.

+2

Algunas respuestas aquí no son conscientes del concepto de tabulaciones (ver http : //www.gnu.org/software/emacs/manual/html_node/emacs/Tab-Stops.html y http://www.jwz.org/doc/tabs-vs-spaces.html). @ckal, Nick-McCowin y user275640 son respuestas correctas. – Jonke

+0

@Jonke publicó una nueva solución para determinar correctamente la tabulación con hasta 4 u 8 espacios. – HappyTown

Respuesta

0

Puede utilizar la función Reemplazar:

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

suena como si quisiera que los resultados se alineen aún en las pestañas –

+0

No funciona, ya que no tiene en cuenta las pestañas que ya no están alineadas con el tabulador (consulte la respuesta @HappyTown). Asumiendo que el ancho de tabulación de 4 "aa \ tb" se convierte en "aa____b" no en "aa__b". – Sprotty

-1

¿Quieres ser capaz de convertir una ficha para espacios N? Una opción rápida y sucia es:

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

Obviamente N tiene que ser definido en alguna parte, ya sea la entrada del usuario o en el programa en otro lugar.

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

No funciona, ya que no tiene en cuenta las pestañas que no están alineadas con el ancho de tabulación (consulte la respuesta de @HappyTown). – Sprotty

15

Lamentablemente, debe suponer cuántos espacios representa una pestaña. Debe establecer esto en un valor fijo (como los cuatro mencionados) o convertirlo en una opción de usuario.

La forma más rápida de hacerlo es .NET es (estoy usando C#):

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

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

A continuación, puede cambiar la variable TabLength a cualquier cosa que desee, por lo general como se mencionó anteriormente, cuatro espacios.

¡Las pestañas en todos los sistemas operativos tienen la misma longitud, una sola pestaña! Lo que difiere es la forma en que el software los muestra, por lo general, este es el ancho equivalente de cuatro espacios, y esto también supone que la pantalla usa una fuente de ancho fijo como Courier New.

Por ejemplo, mi IDE of choice me permite cambiar el ancho del carácter de tabulación al valor que me conviene.

+2

Las pestañas tienen en cuenta los caracteres UP TO TabSpace, no exactamente tantos caracteres. –

+0

@JoelCoehoorn publicó una nueva solución para determinar correctamente la tabulación con hasta 4 u 8 espacios. – HappyTown

+0

Esto NO es una solución, ya que no tiene en cuenta las pestañas que ya no están alineadas con la pestaña (ver respuesta @HappyTown). Suponiendo que el ancho de tabulación de 4 "aa \ tb" se convierta en "aa____b" no "aa__b" – Sprotty

-1

No estoy muy seguro de lo que quiere decir con "No puedo suponer cuántos espacios debe abarcar una pestaña", pero este ejemplo reemplazará las pestañas con cualquier cantidad de espacios que especifique.

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

No funciona, ya que no tiene en cuenta las pestañas que no están alineadas ya con tabulaciones (consulte la respuesta @HappyTown). Asumiendo que el ancho de tabulación de 4 "aa \ tb" se convierte en "aa____b" no en "aa__b". – Sprotty

3

Creo que lo que quiere decir es que desea reemplazar las pestañas con la cantidad efectiva de espacios a los que fueron expandidos. La primera forma en que se me ocurre no implica expresiones regulares (y no sé si este problema podría resolverse con ellas).

  • Pase la cadena carácter por carácter, haciendo un seguimiento de su posición actual en la cadena.
  • Cuando encuentre una pestaña, reemplácela por N espacios, donde N = tab_length - (current_position % tab_length).
  • Agregue N a su posición actual y continúe a través de la cadena.
6

No estoy seguro de cómo las pestañas se leerán desde un archivo de texto Unix, o cualquiera que sean sus diversos formatos, pero esto funciona para el texto en línea. Tal vez ayude.

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

El concepto se ve bien, pero el + = en la cadena será MUY LENTO en cadenas grandes. – Sprotty

-1

creo que todo el mundo ha cubierto, sino un carácter de tabulación es sólo eso. un personaje ... el personaje está representado por \ t ... cada aplicación puede elegir mostrarlo con un espacio, dos espacios, 4 espacios, un emoticón ... lo que sea ... así que ... no hay una respuesta real a esto.

1

Esto es exactamente lo que están hablando de necesitar. Escribí esto de nuevo en Visual Basic 6.0. Hice algunas actualizaciones rápidas de VB.NET 2010, pero podría ser mejor arreglarlo. Solo asegúrese de configurar el ancho de la pestaña deseada; está configurado a 8 allí. Justo lo envía la cadena, o incluso fijarlos justo dentro de la caja de texto, así:

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

(Si usted está buscando la manera de convertir tabulaciones en espacios en un editor, ver al final de mi respuesta)

Casi 8 años de edad, pero recientemente tuve que reemplazar las pestañas por espacios.

La solución reemplaza la pestaña con hasta 4 u 8 espacios.

La lógica itera a través de la cadena de entrada, un carácter a la vez y realiza un seguimiento de la posición actual (columna #) en la cadena de salida.

  • Si se encuentra con \t (pestaña char) - Comprueba la pestaña siguiente parada, calcula cuántos espacios que necesita para llegar a la siguiente tabulación, reemplaza \ t con los número de espacios.
  • If \n (nueva línea): lo asocia a la cadena de salida y restablece el puntero de posición en 1 en la nueva línea. Las nuevas líneas en Windows son \r\n y en UNIX (o sabores) usan \n, así que supongo que esto debería funcionar para ambas plataformas. He probado en Windows, pero no tengo UNIX a mano.
  • Cualquier otro carácter: lo asocia a la cadena de salida e incrementa la posición.

.

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

El código de llamada sería como

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

cadena de salida sería obtener el valor

I love Yosemite National Park  ,   Grand Canyon, 
     and Zion 

¿Cómo se convierte tabulaciones en espacios en un editor?

Si se topa con esta pregunta porque no puede encontrar la opción de convertir pestañas en espacios en los editores (al igual que hice y pensé en escribir su propia utilidad para hacerlo), aquí es donde se encuentra la opción en diferentes editores -

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

No puedo agregar la primera línea del código, 'using System.Text;', al fragmento de código por algún motivo. Stackoverflow se equivoca con el formato ... – HappyTown

+1

El último texto antes del ejemplo de código es una lista. Las listas usan la misma sangría que las muestras de código para marcar un párrafo de continuación en el mismo elemento de elemento de lista. Normalmente utilizo un único período (.) Para "restablecer" la lista, y luego el código se mostrará correctamente. –

+0

@JoelCoehoorn Gracias por arreglarlo y mostrar cómo solucionarlo. – HappyTown

0

No estoy seguro si mi solución es más eficiente en la ejecución pero es más compacta en el código.Esto está cerca de la solución por @ckal pero vuelve a ensamblar las cadenas divididas usando la función de unión en lugar de '+ ='.

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

Muy pocas respuestas de aquí abandono que significa una ficha el número de espacios a la siguiente pestaña detener, no "cuatro (u ocho) espacios". Algunas respuestas también omiten los retornos de carro y las alimentaciones de línea, y por lo tanto no manejan el contenido de líneas múltiples. Así que sin más preámbulos:

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

(Por cierto, esto también es eficiente en la CPU que no volver a copiar las cadenas gigantes)

Cuestiones relacionadas