2009-02-03 12 views
11

Sto costruendo un parser di testo utilizzando le espressioni regolari. Devo convertire tutti i caratteri di tabulazione in una stringa in caratteri di spazio. Non posso assumere il numero di spazi che una scheda dovrebbe comprendere altrimenti potrei sostituire una scheda con, diciamo, 4 caratteri di spazio. C'è qualche buona soluzione per questo tipo di problema. Ho bisogno di farlo in codice, quindi non posso usare uno strumento esterno.Converti schede in spazi in una stringa .NET


Sfortunatamente, nessuna di queste risposte risolve il problema con cui mi trovo. Sto estraendo testo da file di testo esterni e non posso assumere come sono stati creati o quale sistema operativo è stato utilizzato per crearli. Credo che la lunghezza del carattere di tabulazione possa variare, quindi se incontro una linguetta mentre sto leggendo il file di testo, voglio sapere quanti caratteri spaziali dovrei sostituirlo con.

+2

Alcune risposte qui non sono a conoscenza del concetto di scheda smette (vedi http : //www.gnu.org/software/emacs/manual/html_node/emacs/Tab-Stops.html e http://www.jwz.org/doc/tabs-vs-spaces.html). @ckal, Nick-McCowin e user275640 sono le risposte corrette. – Jonke

+0

@Jonke ha pubblicato una nuova soluzione per determinare correttamente la tabulazione con un massimo di 4 o 8 spazi. – HappyTown

risposta

0

È possibile utilizzare la funzione di sostituire:

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

sembra che desideri che i risultati continuino a essere allineati sui punti di tabulazione –

+0

Non funziona in quanto non tiene conto delle schede che non sono già allineate alla tabulazione (consultare la risposta @HappyTown). Supponendo che la larghezza della tabulazione di 4 "aa \ tb" diventi "aa____b" non "aa__b". – Sprotty

-1

Si vuole essere in grado di convertire una scheda per N spazi? Un'opzione rapida e sporca è:

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

Ovviamente N deve essere definito da qualche parte, sia esso input dell'utente o altrove nel programma.

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

Non funziona in quanto non tiene conto delle schede che non sono allineate alla larghezza di tabulazione (consultare la risposta @HappyTown). – Sprotty

15

Sfortunatamente, è necessario assumere il numero di spazi rappresentati da una scheda. Dovresti impostarlo su un valore fisso (come i quattro citati) o renderlo un'opzione utente.

Il modo più rapido per farlo è NET è (sto usando C#):

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

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

È quindi possibile modificare la variabile TabLength per tutto quello che vuoi, in genere come accennato in precedenza, quattro caratteri di spazio.

Le schede di tutti i sistemi operativi hanno la stessa lunghezza, una scheda! Ciò che differisce è il modo in cui il software li visualizza, tipicamente questa è la larghezza equivalente di quattro caratteri di spazio, e ciò presuppone anche che il display stia usando un font a larghezza fissa come Courier New.

Ad esempio, il mio IDE of choice mi consente di modificare la larghezza del carattere di tabulazione in un valore adatto a me.

+2

Le schede rappresentano i caratteri UP TO TabSpace, non esattamente quelli di molti caratteri. –

+0

@JoelCoehoorn ha pubblicato una nuova soluzione per determinare correttamente il punto di tabulazione con un massimo di 4 o 8 spazi. – HappyTown

+0

Questa NON è una soluzione in quanto non tiene conto delle schede che non sono già allineate con la tabulazione (consultare la risposta @HappyTown). Supponendo che la larghezza della tabulazione di 4 "aa \ tb" diventi "aa____b" non "aa__b" – Sprotty

-1

Non sono proprio sicuro di cosa intendi per "Non posso supporre quanti spazi deve contenere una scheda", ma questo esempio sostituirà le schede con qualsiasi numero di spazi specificato.

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

Non funziona in quanto non tiene conto delle schede che non sono già tab-stop allineate (vedere risposta @HappyTown). Supponendo che la larghezza della tabulazione di 4 "aa \ tb" diventi "aa____b" non "aa__b". – Sprotty

3

Penso che vuoi dire sostituire le schede con la quantità effettiva di spazi in cui sono state espanse. Il primo modo che viene in mente non riguarda le espressioni regolari (e non so che questo problema potrebbe essere risolto con loro).

  • Attraversare la stringa carattere per carattere, tenendo traccia della posizione corrente nella stringa.
  • Quando si trova una scheda, sostituirla con N spazi, dove N = tab_length - (current_position % tab_length).
  • Aggiungi N alla posizione corrente e continua con la stringa.
6

Non sono sicuro di come verranno letti i tab da un file di testo Unix o da qualsiasi altro formato, ma questo funziona per il testo in linea. Forse aiuterà.

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

Il concetto sembra OK, ma il + = sulla stringa sarà VERY SLOW su stringhe grandi. – Sprotty

-1

Penso che tutti lo abbiano coperto, ma un carattere di tabulazione è proprio questo. un personaggio .. il personaggio è rappresentato da \ t .. ogni applicazione può scegliere di visualizzarlo con uno spazio, due spazi, 4 spazi, una faccina .. qualunque cosa .. quindi .. non c'è una vera risposta a questo.

1

Questo è esattamente quello di cui stanno parlando. Ho scritto questo in Visual Basic 6.0. Ho fatto alcuni rapidi aggiornamenti di VB.NET 2010, ma potrebbe esserci un po 'di miglioramento. Basta essere sicuri e impostare la larghezza della tabulazione desiderata; è impostato a 8 in là. Basta inviare la stringa, o anche correggerli proprio all'interno del testo in questo modo:

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

(Se siete alla ricerca di come convertire le tabulazioni in spazi in un editor, vedere alla fine della mia risposta)

Domanda di almeno 8 anni, ma di recente ho richiesto di sostituire le schede con gli spazi.

La soluzione sostituisce la scheda con fino a 4 o 8 spazi.

La logica itera attraverso la stringa di input, un carattere alla volta e tiene traccia della posizione corrente (colonna #) nella stringa di output.

  • Se incontra \t (scheda char) - Finds tabulazione successiva, calcola quanti spazi di cui ha bisogno per arrivare alla fermata successiva scheda, sostituisce \ t con quelli numero di spazi.
  • Se \n (nuova riga) - Viene aggiunto alla stringa di output e Reimposta il puntatore di posizione su 1 sulla nuova riga. Le nuove linee su Windows sono \r\n e su UNIX (o aromi) usano \n, quindi suppongo che questo dovrebbe funzionare per entrambe le piattaforme. Ho provato su Windows, ma non ho UNIX a portata di mano.
  • Qualsiasi altro carattere: lo aggiunge alla stringa di output e incrementa la posizione.

.

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

Il codice chiamante sarebbe come

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

stringa di uscita otterrebbe valore

I love Yosemite National Park  ,   Grand Canyon, 
     and Zion 

Come faccio a convertire le tabulazioni in spazi in un editor?

Se ci si è imbattuti in questa domanda perché non è possibile trovare l'opzione per convertire le schede in spazi negli editor (proprio come ho fatto io e ho pensato di scrivere la propria utilità per farlo), qui è dove si trova l'opzione in diversi editor -

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

Non riesco ad aggiungere la prima riga del codice, 'usando System.Text;', allo snippet di codice per qualche motivo. StackOverflow scombina con la formattazione. – HappyTown

+1

L'ultimo testo prima dell'esempio di codice è un elenco. Gli elenchi utilizzano lo stesso rientro degli esempi di codice per contrassegnare un paragrafo di continuazione nello stesso elemento dell'elemento di elenco. In genere utilizzo un singolo punto (.) Per "ripristinare" l'elenco, quindi il codice verrà visualizzato correttamente. –

+0

@JoelCoehoorn Grazie per averlo sistemato e mostrato come risolverlo. – HappyTown

0

Non sono sicuro se la mia soluzione è più efficiente in esecuzione ma è più compatta nel codice.Questo è vicino alla soluzione di @ckal ma riassembla le stringhe divise usando la funzione Join piuttosto che '+ ='.

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

Un bel paio di risposte su qui trascurare che una scheda significa il numero di spazi alla scheda successiva fermare, non "quattro (o otto) spazi". Parecchie risposte trascurano anche i ritorni a capo e i feed di riga e quindi non gestiscono il contenuto multilinea. Quindi, senza ulteriori indugi:

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

(A proposito, questo è anche CPU efficiente in quanto non ricopiare le stringhe giganti)