Tabs durch Leerzeichen ersetzen

Gast #3768526
Lesenswert?

Ich suche ein Commandline-Tool um die nicht ungewöhnliche Aufgabe zu 
lösen, Tabs durch Leerzeichen zu ersetzen.

Ich hatte da mal irgendwo einen Fetzen im Internet gefunden, das war 
eigentlich nur ein sed-Aufruf. Und es wurden leider nur Stur die Tabs 
durch 4 Leerzeichen ersetzt. Allerdings müsste ja die Position des 
ersten Tabs überprüft und gegebenfalls durch weniger Leerzeichen ersetzt 
werden, um Verschiebungen zu vermeiden.

Hat da jemand zufällig was in der Richtung? (bash, perl, python)

Gruß
Gast #3768541
Lesenswert?

Der Entwickler schrieb:
> Wie viele Leerzeichen durch ein TAB dargestellt werden, ist alleine
> Sache des Editors/Betrachters und nicht in der Datei abgespeichert.
Genau. Oder eben im Skript/Tool hinterlegt, der diese Wandlung 
automatisiert vornimmt. Luxus wäre natürlich, diese Zahl dem Skript/Tool 
als Parameter übergeben zu können.

> Tabs kann man z.B. auch mit Notepad++ ersetzen.
Kann man dieses Feature von der Kommandozeile ansprechen?
Gast #3768555
Lesenswert?

Stefan P. schrieb:
> Das mit der "Position des ersten TABs" verstehe ich nicht so recht -
> Geht es um C-Code o.ä.? TABs haben dort doch keine Position, sondern es
> sind halt mehrere TABs nacheinander.

er meint damit, das bei (einigen) Editoren die Tabs immer zu einer 
Position die durch 4 Teilbar ist springen.

ein
[space][Tab]text]
[space][space][Tab]text]
[space][space][space][Tab]text]

sieht gleich aus, der text beginn jeweils an Pos 4.
Gast #3768563
Lesenswert?

Peter II schrieb:
> er meint damit, das bei (einigen) Editoren die Tabs immer zu einer
> Position die durch 4 Teilbar ist springen.
>
> ein
> [space][Tab]text]
> [space][space][Tab]text]
> [space][space][space][Tab]text]
>
> sieht gleich aus, der text beginn jeweils an Pos 4.

Genau das.
Anstatt also blind einen Tab durch exakt n Leerzeichen zu ersetzen muss 
n abhängig von der Position berechnet werden (n = SPACE_FOR_TAB - (pos % 
SPACE_FOR_TAB), oder so ähnlich).

Wundert mich dass es sowas noch nicht gibt, muss mich wohl doch in perl 
einarbeiten.
Gast #3768654
Lesenswert?

Oliver S. schrieb:
> Max W. schrieb:
>> war
>> eigentlich nur ein sed-Aufruf.
>
> Eigentlich kann sed alles. Du musst nur jemanden finden, der dir den
> regulären Ausdruck dazu bastelt ;)
>
> Oliver

In diesem speziellen Fall würde ich lieber awk nehmen, das Werkzeug ist 
ein wenig universeller.

Im Anfangsbereich
1
BEGIN{...}
 die Größe eines Tabstops definieren.
Zeilenweise einlesen,
In Schleife die Position(en) der/des Tabs bestimmen,
passende Menge ' ' einfügen,
wegschreiben, fertich!
Gast #3768674
Lesenswert?

Norbert schrieb:
> Im AnfangsbereichBEGIN{...} die Größe eines Tabstops definieren.
> Zeilenweise einlesen,
> In Schleife die Position(en) der/des Tabs bestimmen,
> passende Menge ' ' einfügen,
> wegschreiben, fertich!

und wo ist das der Vorteil von AWK? Das kann man genauso in Perl machen.
Gast #3768788
Lesenswert?

Danke Yalu, das werd ich mir mal alles zu Gemüte führen.

Nichtsdestotrotz hab ich in der Zwischenzeit mal folgendes 
zusammengeschustert, das macht (bis jetzt) genau was es soll:
1
inFile = open("./test.txt", "r")
2
outFile = open("./test2.txt", "w")
3

4
for line in inFile:
5
    idx = line.find('\t')
6
    while(idx != -1):
7
        spaceCnt = 4 - (idx % 4)
8
        if (spaceCnt == 1):
9
            line = line.replace("\t", " ", 1)
10
        elif (spaceCnt == 2):
11
            line = line.replace("\t", "  ", 1)
12
        elif (spaceCnt == 3):
13
            line = line.replace("\t", "   ", 1)
14
        elif (spaceCnt == 4):
15
            line = line.replace("\t", "    ", 1)
16
        idx = line.find('\t')
17
        
18
    outFile.write(line)
19

20
inFile.close()
21
outFile.close()

Ist mein erster Kontakt mit Python und ich hab das nur so 
zusammengepfriemelt. Execptions werden noch nicht aufgefangen. Und die 
hartcodierte "4" würd ich gern durch Generik ersetzen, aber für 15min 
basteln bin ich schon recht zufrieden :-)

Und ja, ich weiß dass Perl für sowas wahrscheinlich performanter ist und 
mein Python-Stil vermutlich murks ist :p
Moderator #3769061
Lesenswert?

Das sieht doch schon gut aus.

Für beliebige Tab-Breiten ersetzt du einfach dieses
1
        spaceCnt = 4 - (idx % 4)
2
        if (spaceCnt == 1):
3
            line = line.replace("\t", " ", 1)
4
        elif (spaceCnt == 2):
5
            line = line.replace("\t", "  ", 1)
6
        elif (spaceCnt == 3):
7
            line = line.replace("\t", "   ", 1)
8
        elif (spaceCnt == 4):
9
            line = line.replace("\t", "    ", 1)
10
        idx = line.find('\t')

durch dieses:
1
        spaceCnt = tabWidth - (idx % tabWidth)
2
        line = line.replace("\t", spaceCnt * " ", 1)
3
        idx = line.find('\t')

In tabWidth muss dabei der entsprechende Wert (4, 8 oder was auch immer)
stehen.
#3770162
Lesenswert?

Der Entwickler schrieb:
> Wie viele Leerzeichen durch ein TAB dargestellt werden, ist alleine
> Sache des Editors/Betrachters und nicht in der Datei abgespeichert.

Nicht ganz, es gibt Ausnahmen: Vim z.B. versteht folgende Zeile irgendwo 
im Text:
1
# vim:ts=3:sw=3:

Das bedeutet tabsize=3 und shiftwidth=3. Der Editor weiß dann, wie er 
die Datei darstellen muss.

Das # am Zeilenanfang ist das Kommentarzeichen der jeweiligen 
Programmiersprache - kann also auch // o.Ä. sein.
Gast #3771693
Lesenswert?

Yalu X. schrieb:
> Das sieht doch schon gut aus.
>
> Für beliebige Tab-Breiten ersetzt du einfach dieses
>
>
1
>         spaceCnt = 4 - (idx % 4)
2
>         if (spaceCnt == 1):
3
>             line = line.replace("\t", " ", 1)
4
>         elif (spaceCnt == 2):
5
>             line = line.replace("\t", "  ", 1)
6
>         elif (spaceCnt == 3):
7
>             line = line.replace("\t", "   ", 1)
8
>         elif (spaceCnt == 4):
9
>             line = line.replace("\t", "    ", 1)
10
>         idx = line.find('\t')
11
>

und dann ersetzt du das durch:
1
line = line.replace("\t", " "*spaceCnt, 1)
;-)
Gast #3771748
Lesenswert?

Max W. schrieb:
> Allerdings müsste ja die Position des
> ersten Tabs überprüft und gegebenfalls durch weniger Leerzeichen ersetzt
> werden, um Verschiebungen zu vermeiden.
Liest sich für mich eher nach einer Aufgabe für ein Einrückungstools, 
evtl astyle? Oder sed und dann astyle?
1
sed 's/\t/        /g' in.dat > out.dat
1
astyle --style=linux file.dat
Gast #3772304
Lesenswert?

Uhu Uhuhu schrieb:
> Εrnst B✶ schrieb:
>> Perl liefert "a2p" mit, damit kann man das AWK-Script gleich wieder
>> ver-perl-en.
>
> Das ist dann für durch Perl versaute Programmierer, die mit AWK nicht
> klar kommen...

Mir fallen da auf Anhieb zwei Kollegen ein, die am liebsten alles 
Mögliche in Perl programmieren würden.

Da kommt einem sofort der Satz in den Sinn:
1
Wenn man einen Hammer in der Hand hat,
2
dann sieht plötzlich alles wie ein Nagel aus!

Nachsatz:

Nur gut das das keine Java oder .NET Fans sind;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren