• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[gelöst] Leerzeichen und Tabs aus Textdatei entfernen...

rethus

Advanced Hacker
Hallo,
ich möchte aus einer Textdatei alle Tabs entfernen, und zusätzlich alle Zeilenumbrüche, die von 2 Tabs gefolgt sind.

Dazu hab ich mich im Netz schon was kundig gemacht und folgenden Ansatz gefunden:

Code:
tr -s [:blank:] ' ' < eingangstext.txt > ausgangstext.txt

http://www.linux-user.de/ausgabe/2005/02/073-zubefehl/index.html

Allerdings fehlt mir noch die genaue Kombination, das alles rund läuft.
Denn der obige Befehl zieht lediglich Leerzeichen >2 raus.

Wie gesagt benötige ich aber auch die funktion, das nur dir Zeilenumbrüche entfernt werden, die von Tabs gefolgt sind.

Hat jemand eine Idee?
Vielleicht kann mir da jemand helfen.
 

oc2pus

Ultimate Guru
Reguläre Ausdrücke bestimmen mit diesem kleinen Tool:
http://txt2regex.sourceforge.net/

Txt2regex is a Regular Expression Wizard that converts human sentences to regexes. In a simple interactive console interface, the user answer questions and the program build the regexes for more than 20 programs, like Vim, Emacs, Perl, PHP, Python, Procmail and OpenOffice.org. It is a Shell Script 100% written with Bash builtin commands. No compilation or extra commands are needed, just download and run.

Supported programs (23)
AWK, ed, egrep, Emacs, expect, find, gawk, grep, lex, lisp, mawk, MySQL, OpenOffice.org, Perl, PHP, Postgres, Procmail, Python, SED, Tcl, VBscript, VI, Vim.
 
OP
R

rethus

Advanced Hacker
Naja, mir würde schon aussreichen zu wissen, was ein leerzeichen und was ein Tab in Form von Regulären Ausddrücken wäre.

PS: Hab noch folgende möglichkeit gefunden, wobei mir da auch wieder die Suche nach dem genauen Muster fehlen: "Zeilenumbruch >> 2x Tab"

Code:
sed -e '/^[ ]*$/d' AlteDatei > NeueDatei
(ist auch wieder nur für leerzeichen...
 

oc2pus

Ultimate Guru
rethus schrieb:
Naja, mir würde schon aussreichen zu wissen, was ein leerzeichen und was ein Tab in Form von Regulären Ausddrücken wäre.

und warum lässt du es dir dann nicht von dem kleinen Tool verraten ?
das ist ein bash-script, ist also in null-komma-Nix installiert ...

btw: "\t" ist ein TAB
 
OP
R

rethus

Advanced Hacker
Ok, hab mir das Progie gezogen... ist n tolles Programm... Sieht komlizierter aus als ist.... werde ich sicher noch oft zum Coden brauchen, aber mit meinem Problem bin ich immer noch nicht weiter...

Also ich habe Beispielsweise folgen Text:
(Ich füg mal >> f+r Zeilenumbruch und -| für Tab ein

Code:
UKZLAG>>
Attribut FAHR_UKZLager >>
Definiert durch Basisattribut	:	UnternehmenKZLager >>
Definition Basisattribut	:	Unternehmenskennzeichen LAGer . >> Bezeichnet zusammen mit der Filial->>
-|    -|		nummer des Lagers (FILLAG) eindeutig das Lager. Standardbestandteil >>
-|  -|		des Primärschlüssels der meisten LVS-Tabellen. >>
Einschränkung Wertebereich	:	Wird in den LVS-Programmen durch eine Parameterdatei beim Start der >>
-|  -|		Server-Programme eingestellt.

Also vor dem Doppelpunkt ist eine Bezeichnung der Zeile, und dahinter der Text, der ohne Umbrüche und Tabs dargestellt werden soll.

Mein Ansatz war:
  • 1. tr -s '\n\t\t' '\n' < db_daten.txt >db_new.txt
    2. sed -e '/^[\n\t\t]*$/d' db_daten.txt >db_new.txt

1. zog alles an Zeilenumbrüchen raus, so das ich einen Textbrei erhalte...
2. bewirkt irgendwie überhaupt nichts
 

oc2pus

Ultimate Guru
probiere mal:

Code:
sed -e '/[\t].*\|[\n][\t]\{2\}.*/d' < EINAGBE.txt

durch "|" wird das ODER dargestellt
aslo entweder TAB gefolgt von Zeichen
ODER ZeilenUmbruch gefolgt von TAB TAB wertden durch "NIX" ersetzt.
 
OP
R

rethus

Advanced Hacker
Danke, das ist schon ganz gut, aber leider funzt es noch nicht...
Das Problem ist, das die Zeilen jeweils gelöscht werden, anstatt die entsprechenden Zeichen einfach rauszuziehen.

Derzeit habe ich folgenden Befehl:
Code:
sed -e '/[\t]\{2\}.*/g' db_daten.txt > db_new.txt
 

oc2pus

Ultimate Guru
rethus schrieb:
Danke, das ist schon ganz gut, aber leider funzt es noch nicht...
Das Problem ist, das die Zeilen jeweils gelöscht werden, anstatt die entsprechenden Zeichen einfach rauszuziehen.
ok, dann muss am Ende /d durch /g erstezt werden so wie du es getan hast.

lass deinen ersten Befehl mit dem "tr ... " mal weg, dann sollte es besser funktionieren. Oder hast du den gar nicht mehr in Betrieb ?
 
OP
R

rethus

Advanced Hacker
Den hab ich gar nicht mehr genutzt.

Bei obiger Befehlsingabe löscht er die Zeilen auch, allerdings bleibt die Zeile (leer) bestehen.
Bei /d nimmt de3r die Zeile ganz raus.
 

oc2pus

Ultimate Guru
bei deinem Befehl werde 2 TAB gefolgt von belibigen Zeichen durch NIX ersetzt, deshalb.

lass mal den ".*" weg, dann werden nur die TABTAB Sequenzen zu NIX
 

oc2pus

Ultimate Guru
AARG es fehlte ja auch was wichtiges das "s" für substitute

entferne alle TABs
Code:
sed -e 's/[\t]//g' <EINGABE.TXT

du kannst dann konkatenieren
Code:
sed -e 'expr1' -e 'expr2' < EINGABE.TXT

habe grade keinen sed-fähigen Rechner hier ;)[/code]
 
OP
R

rethus

Advanced Hacker
Also das ist es noch nicht so ganz.
Das Problem ist folgendes:

Wenn ich Ihm sage:
Code:
sed -e 's/[\t]\{2\}//g' text1.txt > text2.txt
Macht er auch brav alles - also zieht alle doppelten tabs raus.

Aber sobald ich Ihm mit einem Zeilenumbruch kommen will:
Code:
sed -e 's/[\n][\t]\{2\}//g' text1.txt > text2.txt
, macht er gar nichts mehr (die Datei sieht dann genauso aus wie die Quelldatei... keine Änderung)

Woran kann das nur liegen? Habs auch schon mit [\r] anstatt [\n] versucht... nix :-(
 

sc_m

Member
Das Problem ist, dass sed grundsätzlich zeilenweise arbeitet, d.h. bei einem "\n" wird der aktuelle Puffer abgearbeitet und anschließend verworfen. Man kann aber mit einem zweiten Puffer ein wenig herumspielen:
Code:
echo -e "eine Zeile,\n\t\tweiter,\n\t\tnoch weiter\nletzte Zeile\n" |
sed -ne '/^\t\t/{H;x;s/\n\t\t/ /;x;D}; x; 2,$p'
Ist es das, was du wolltest?

Edit: Etwas Kosmetik.
 

abgdf

Guru
Hallo,

ich hab hier eine Lösung in Python gebastelt.

Eingabedatei heißt "in", Ausgabedatei heißt "out", jeweils im Verzeichnis des Skripts. Bitte ggf. entsprechend ändern:

Code:
#!/usr/bin/env python
# -*- coding: utf8 -*-

f=file("in","r")
a=f.readlines()
f.close()

c=[]

for i in range(len(a)):

    c.append(a[i].replace("\t",""))

    if a[i][0:2]=="\t\t" and i != 0:
        c.pop()
        c.pop()
        c.append((a[i-1].rstrip("\n")+a[i]).replace("\t",""))

f=file("out","w")
f.writelines(c)
f.close()

Wie findest Du das so ?

Viele Grüße
 

abgdf

Guru
@jengelh:
Ist ja echt krass, was Du alles in einer Zeile unterbringen kannst :shock: :) !
Ich brauch da schon etwas länger:

Code:
#!/usr/bin/env perl
use warnings;
use strict;

open (F, "in") or die;
my @a=<F>;
close(F);

my @c=();
my $ci=0;
my $i=0;

for ($i=0;$i<=$#a;$i++)
{
$c[$ci]=$a[$i];
$c[$ci] =~ s/[\t]//g;
$ci++;

if (substr($a[$i],0,2) eq "\t\t" && $i != 0)
{
pop(@c);
pop(@c);
$ci -= 2;

$c[$ci]=$a[$i-1];
chomp($c[$ci]);
$c[$ci]=$c[$ci].$a[$i];
$c[$ci] =~ s/[\t]//g;
$ci++;
}
}

open (F, ">out") or die;
print (F @c);
close(F);

Viele Grüße
 
abgdf schrieb:
@jengelh:
Ist ja echt krass, was Du alles in einer Zeile unterbringen kannst :shock: :) !
Weniger ist besser, hat weniger potentielle Fehlerquellen.
Ich brauch da schon etwas länger:

Code:
#!/usr/bin/env perl
use warnings;
use strict;

open (F, "in") or die;
my @a=<F>;
close(F);

my @c=();
my $ci=0;
my $i=0;

for ($i=0;$i<=$#a;$i++)
{
$c[$ci]=$a[$i];
$c[$ci] =~ s/[\t]//g;
$ci++;

if (substr($a[$i],0,2) eq "\t\t" && $i != 0)
{
pop(@c);
pop(@c);
$ci -= 2;

$c[$ci]=$a[$i-1];
chomp($c[$ci]);
$c[$ci]=$c[$ci].$a[$i];
$c[$ci] =~ s/[\t]//g;
$ci++;
}
}

open (F, ">out") or die;
print (F @c);
close(F);

Viele Grüße
Na mit deinem @c Array machst du keinen glücklich, denn nach jedem \n fängt ein neues Element an. Genau das aber stört, wenn du gerade \n im Suchen-und-Ersetzen-Muster hast.
 
OP
R

rethus

Advanced Hacker
Wow, danke schon mal für Eure Mühe.
Werde mich mal mit den verschiedenen Lösungen auseinandersetzen und euch dann eine Rückmeldung geben.

Danke schon mal!
 
Oben