Zeichen ersetzen und mit Leerzeichen auffüllen

H

herzbeat

Don
Hallo Leute,

ich benötige mal kurz Eure Unterstützung. Ich habe eine Datei mit folgendem Inhalt, hier ab Spaltenposition 75, das Feld muss eine feste Länge von 30 Zeichen haben.

a/aaaaa
ccc/cccccccc
bb/bbb

Ich möchte nun für alle Zeilen, die Zeichen vor dem Slash / entfernen und die Anzahl der entfernten Zeichen als Leerzeichen hinten wieder anfügen, damit die Feldlänge von 30 Zeichen erhalten bleibt.

Das ganze läuft in einem shell-script unter AIX (ksh)
Nur finde ich keinen geeigneten Lösungsansatz.

Danke und Grüße
2R
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Betreff sollte natürlich heissen:

Zeichen ENTFERNEN und mit Leerzeichen auffüllen.

2R
 
Zuletzt bearbeitet:
step away, i know regular expressions!

*perl*
Code:
perl -ne 'use English; if (m{^([[:alpha:]])\1*(?=/)}) {$_ = $POSTMATCH;chomp; print; {foreach (1..$+[0]) {print " "}; print "\n"}}'

:s
 
naja, dann zun beispiel so:
Code:
while read line; do
    afterSlash=$(echo "$line"|sed -r 's#^[[:alnum:]]+/#/#')
    beforeSlashCount=$(($(echo "$line"|egrep -o '^[[:alnum:]]+/'|wc -c)-2))
    printf "$afterSlash"
    for i in $(seq 1 $beforeSlashCount); do
        printf " "
    done
    printf "\n"
done
das funktioniert so in bash. ich habe den "-r" switch für sed benutzt, da solltest du mal nachsehen, ob dein sed das kann. außerdem benuzte ich egrep. die posix-command substitution $(...) sollte ksh iirc können, muss aber nicht...und dieses hier $((ausdruck)) gibt das ergebnis einer ganzzahl rechenoperation in bash zurück. vielleicht musst du dafür "externe" tools verwenden. bc hast du, oder?
dann könntest du die beforeSlashCount zuweisung so verändern:
Code:
beforeSlashCount=$(echo "$(echo "12345/bla"|egrep -o '^[[:alnum:]]+/'|wc -c) - 2"|bc -q)
außerdem matche ich hier alle alphanumerischen zeichen vor einem slash (nicht wie im perl-one-liner alle sich wiederholenden buchstaben..)
 
Hallo Gott_in_Schwarz,

könnte funktionieren. Das werde ich mal am WE ausprobieren.

Da das ganze in einem bereits existierendem Script abläuft, müßte ich die Schleife irgendwie mit der Eingabe/Ausgabedatei verknüpfen:

Code:
while read < $file1; do
Code:
Ausgabe > $file2 ???

Sorry, aber was meinst Du mit "bc hast du"

2r
 
Hallo
Warum nimmst du nicht einfach Parameterexpansion.
Das kennt auch die ksh
Das ganze mit printf kombiniert, bringt dir dein Ergebnis prozesssparend und einfach.
30 Zeichen Spaltenbreite linksbündig.
Code:
while read line;
do
printf "%-30s\n" ${line#*\/}
done <input >output

Gruß Wolfgang
 
Zuletzt bearbeitet:
Guten morgen,

also was gibt es zu berichten:

@Gott_in_schwarz:

Leider habe ich keine r-Option bei meinem sed, somit bricht die Schleife an dieser Stelle schon ab.
2. Variante aus o.g. Gründen nicht getestet.

bc kannte ich bislang nicht, ist aber vorhanden.

@Wolfgang
Ich stehe ja auch auf "weniger ist mehr" aber das passt leider nicht. Warum:
Die entsprechenden Zeichen stehen im File ab Spalte 75: aaaa/bbbbbb
Alle Zeichen inklusive "/" müssen entfernt werden, und die Anzahl der entfernten Zeichen müssen bis zur Gesamtlänge von 30 Zeichen hinter bbbbbb wieder aufgefüllt werden.

Das hier:
Code:
printf "%-30s\n"
setzt alle Spalten auf 30 und macht ungewünschte LF

Noch ein paar Ideen ?

Danke und Grüße
2r
 
Hallo
Dann schau dir mal cut und man printf an.
Das war nur ein Beispiel.
Der abschließende Newline ist hier sehr leicht durch ein Trennzeichen deiner Wahl ersetzbar.

Wolfgang
 
Leider habe ich keine r-Option bei meinem sed, somit bricht die Schleife an dieser Stelle schon ab.

hier die zeile mit sed ohne r-switch:
Code:
afterSlash=$(echo "$line"|sed -e 's#^[a-zA-Z0-9]\+/#/#')
wobei das den slash erhält, wie dus ja imho auch im ersten posting gesagt hast:
Ich möchte nun für alle Zeilen, die Zeichen vor dem Slash / entfernen
vs dein neues posting:
Alle Zeichen inklusive "/" müssen entfernt werden
hmpf, aber naja, ich würde dir eh von meiner "lösung" abraten. das ist unnötig komplex, dadurch schlechter wartbar und ziemlich unflexibel, wenn du nicht genau verstehst, was da passiert..
also wenn du wirklich eine konstante "feldbreite" in den zu verändernden zeilen hast kann ich mir keine bessere lösung als die von wolfgang gepostete vorstellen. wobei ich mir da auch nicht mehr so ganz sicher bin:
die Anzahl der entfernten Zeichen müssen bis zur Gesamtlänge von 30 Zeichen hinter bbbbbb wieder aufgefüllt werden.
also haben die zeilen vorher und sollen auch nachher (nach dem löschen dessen, was vor dem slash inklusive slash steht) 30 zeichen länge? oder sind 30 zeichen nach dem jeweiligen string, der dem slash folgt und somit haben die zeilen variable länge? :?
 
Hallo Gott_in_schwarz,

der "/" muss am Ende auch verschwinden, das ist aber nicht das Problem.

Ich habe Deine neue Version getestet, nun hängt es an der -o Option von egrep. AIX ist da echt limitiert. :(
Die Spaltenbreite ist fix mit 30 Zeichen. Ich glaube ich werde mich an Wolfgang`s Vorschlag mit cut und printf weiterversuchen.

Danke jedenfalls für Deine und Wolfgangs Hilfe.

Grüße
2r
 
Hello again,

nach Lektüre von cut,printf und Parameterexpansion etwas schlauer geworden und ich die Originaldatei in 2 Dateien aufteilen, ist mein Ergebnis wie folgt hier Teil2 (ab Spalte 75):

Code:
ELISABETH PAULINE D 3
ALBERTUSJOHANNES VAN H 3
BAS VAN K 113

Die Formatierung der Ausgabe mit printf sieht so aus:

Code:
printf "%-30b%-1b%-10b%-2b%-1s\n"

Es handelt sich um 5 Spalten mit fester Breite die so aussehen müssen:

Code:
<----30------ --------------->1<---10---><21\n
ELISABETH PAULINE             D            3
ALBERTUSJOHANNES VAN          H            3
BAS VAN                       K          113

Würde auch anstandlos funktionieren, aber Problem:
1. Leerzeichen zwischen den Namen werden als neue Spalte interpretiert und somit verschiebt sich leider alles nach rechts
2. In der 3. Spalte (Soll-Breite 10) habe ich in der Quelle keine Zeichen und somit funktioniert die Formatierung mit %-10 nicht, d.h. es wird auf ein Leerzeichen "gekürzt".

Bedankt
2r
 
Hallo zusammen,

nun bin ich mit folgender Lösung zum Ergebnis gekommen:

Code:
while read line;do
        echo "$line" | cut -b 1-74
        done < input.txt > teil1.txt
while read line;do
        echo "$line" | cut -b75-104
        done < input.txt > teil2.txt
while read line;do
        echo "$line" | cut -b105-256
        done < input.txt > teil3.txt
while read line;do
        printf "%-30s\n" "${line##*/}"
        done < teil2.txt > teil22.txt
paste -d "\0" teil1.txt teil22.txt teil3.txt > output.txt

Ist nicht die schönste, aber funktioniert. Anregungen erwünscht. :winke:

2r
 
Zurück
Oben