PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Führende Leerzeichen in Variable einfügen



mumdigau
03.10.06, 15:20
Hallo,

Ich möchte Variable in eine Datei so formatiert ausgeben, daß sie stets 8 Zeichen lang sind. Die Variablen haben 1 bis 8 Ziffern, ggf. sind sie also links mit Leerzeichen aufzufüllen.

Leider steht auf meiner Shell printf nicht zur Verfügung. Ich habe dann versucht, mit wc die Zeichenanzahl zu bestimmen (klappt) und mit sed fehlende Leerzeichen links einzufügen (klappt nicht). Irgendwie kommen die Leerzeichen in den Variablen nicht an. Anscheinend mache ich beim sed-Befehl etwas falsch.

Aber vielleicht gibt es ja auch einen anderen, eleganteren Weg.

Vorab schon einmal vielen Dank für jeden Hinweis.

mumdigau

gmk
03.10.06, 17:27
sed ':a;s/^.\{1,7\}$/ &/;ta'

Einfacher ginge es z.B. mit der zsh ... »print ${(l:8:)var}«

mumdigau
03.10.06, 20:42
sed ':a;s/^.\{1,7\}$/ &/;ta'

Hat leider nicht funktioniert. Sowohl auf der Konsole als auch in der Datei fehlen die führenden Leerzeichen.


Einfacher ginge es z.B. mit der zsh ... »print ${(l:8:)var}«

Klappt auf meiner Bourne Shell nicht. Als Fehlermeldung kommt 'Bad substitution'.

Danke trotzdem.

mumdigau

marce
03.10.06, 20:47
"geht nicht" und "klappt nicht" sind 2 recht aussagekräftige Fehlermeldungen.

Poste doch mal das, was Du schon hast (z.B. die sed-Reg-Ex) und dann können wir daran weiterbasteln...

mumdigau
03.10.06, 21:01
Nun, ich habe lediglich den sed-Vorschlag von @gmk aufgegriffen und auf die Konsole und eine logfile ausgegeben:

ber=$ber | sed ':a;s/^.\{1,7\}$/ &/;ta'
echo $ber
echo $ber >>/tmp/test.log

ber enthält zum Zeitpunkt des Aufrufs eine 5-stellige Ziffer. Es hätten also 3 Leerzeichen links eingefügt werden müssen.

mumdigau

gmk
03.10.06, 21:32
Deine Zuweisung sieht komisch aus...
Das sed-Zeug wird wahrscheinlich auch funktionieren. Nur scheint deine Shell die Leerzeichen bei der Variablenzuweisung zu löschen. Macht bash/dash hier auch (zsh jedoch nicht)

% #zsh
% var=" 12345"; print $var
12345
% dash
$ set -x
$ var=123
$ var=$(echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta');echo $var
+ echo 123
+ sed :a;s/^.\{1,7\}$/ &/;ta
+ var= 123
+ echo 123
123

Lösungsmöglichkeiten:
Erst die endgültige Ausgabe anpassen.
Versuchen deine Shell zu überreden dies zu unterlassen.
Andere Shell benutzen

mumdigau
03.10.06, 22:01
@gmk

Danke für Deine ausführliche Antwort.

Ich habe auch deine Zuordnung

var=$(echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta')

probiert: noop.

Was meinst Du mit 'Erst die endgültige Ausgabe anpassen'? Wahrscheinlich nicht die Variable selbst verändern, sondern erst das Schreiben in die Datei, oder? Ja, das war mein erster Ansatz. Aber leider steht printf nicht zur Verfügung. Gibt es andere Möglichkeiten, z. B. mittels awk?

mumdigau

gmk
03.10.06, 22:19
Was meinst Du mit 'Erst die endgültige Ausgabe anpassen'? Wahrscheinlich nicht die Variable selbst verändern, sondern erst das Schreiben in die Datei, oder? Ja, das war mein erster Ansatz. Aber leider steht printf nicht zur Verfügung. Gibt es andere Möglichkeiten, z. B. mittels awk?
Hmm, einfach die Ausgabe von sed umleiten? Also
echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta' > $file

Nunja, mit 'nem passend gesetzten IFS (warum auch immer, hätte vermutet, dass die Anführungszeichen reichen) hab ich die dash hier dazu bekommen den Wert inklusive Leerzeichen zuzuweisen:
% dash (23:12:04)
$ IFS=$'\n';var=123;var=$(echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta');echo $var
123

mumdigau
03.10.06, 23:45
Hmm, einfach die Ausgabe von sed umleiten? Also
echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta' > $file

Klappt nicht (she. #5)



Nunja, mit 'nem passend gesetzten IFS (warum auch immer, hätte vermutet, dass die Anführungszeichen reichen) hab ich die dash hier dazu bekommen den Wert inklusive Leerzeichen zuzuweisen:
% dash (23:12:04)
$ IFS=$'\n';var=123;var=$(echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta');echo $var
123

%dash kann ich natürlich nicht, da auf Bourne Shell. Was setze ich stattdessen?

mumdigau

suck
04.10.06, 00:21
Viel zu umständlich aber geht:
FILE=test.txt
VAR="1255"
COUNT=$(calc 9 - $(echo $VAR | wc -c))
while [[ `echo $COUNT` > 0 ]]; do echo -n " " >> $FILE && COUNT=$(calc $COUNT-1);done
echo $VAR >> $FILE
Edit: Hab's ma in mehr als eine Zeile gepackt ;)

mumdigau
04.10.06, 00:41
Danke @suck.

Leider kann meine Shell 'calc' nicht. Kann man das irgendwie anders lösen?

mumdigau

suck
04.10.06, 00:43
calc installieren! Gehört auf jedes anständige System..

mumdigau
04.10.06, 01:17
Ja, Du magst recht haben.

Ich tummel mich hier auf einem Digital Receiver mit Linux (DBox2). Bisher bin ich mit (einfachen) Scripten klargekommen, aber nun stoße ich anscheinend an die Grenzen.

Suche gerade ohne Erfolg nach einem Download-Link für calc. Tip?

mumdigau

suck
04.10.06, 02:08
Sag das doch direkt! Das bedeutet nämlich zudem, dass Du A) "wc" nicht hast und B) "sed" nicht hast und C) "busybox" nutzt und D) deine Shell "ash" heisst.

Ok, dann is calc natürlich blöd, da es auch gestrippt recht gross ist. Am einfachsten wäre, selber nen Prog zu schreiben. Das Prog sieht so aus:


#include <stdio.h>
int main(int argc, char *argv[]){
printf("%8s\n", argv[1]);
return 0;
}Aber freu Dich nicht zu früh. Du musst das Prog nämlich gegen Busybox linken und nicht wie üblich gegen die glibc! Ach ja, so ne dbox2 mit Neutrino hab ich auch ; )

Gruss..

Edit: Ansonsten würd ich mir mal die Doku von ash anschauen.. vielleicht geht es ja doch irgendwie mit der Shell. Andere Frage, kannst du Zahlen nicht einfach so in ne Datei schreiben und sie später auf nem normalen Linux-Rechner formatieren?

mumdigau
04.10.06, 03:02
Nun, wc (A) und sed (B) kann ich, da ich die sog. Enhanced Buybox 1.03 installiert habe. Wieso ash? Ich dachte bisher, es ist Bourne, da alle Scripts mit #!/bin/sh beginnen.

Ich kann natürlich die Datei mit den Variablen "as is" bauen und anschließend die Datei editieren (unter Windows [z. B. mit Bulk Rename Utility]! Ich habe kein Linux auf meinen Rechnern). Aber was wäre das für eine Schlappe für Linux!

calc dürfte eine Nummer zu groß für meine betagte DBox sein. Warum nicht (wie?) eine Lösung über expr?

mumdigau

suck
04.10.06, 04:00
/bin/sh ist nen Link auf die ash. ash ist kompatibel zur sh. wenn du sh eingibst, steht da auch, dass es die ash ist.

Das ist keine Schlappe für Linux. Du musst das 5 Zeilen lange Porgramm nur richtig kompiliert bekommen - dann geht es ; )

Ausserdem klappt auch der sed Aufruf, der oben (#8) gepostet wurde (grad getestet) ganz wunderbar. Nur deine Abwandlung aus Antwort #5 geht natürlich nicht.

gmk
04.10.06, 07:37
Klappt nicht (she. #5)

%dash kann ich natürlich nicht, da auf Bourne Shell. Was setze ich stattdessen?
Nunja, damit rufe ich einfach die »Debian Almquist Shell« (kurz dash) auf. Darauf ist bei mir /bin/sh gelinkt. Standardmäßig läuft hier die zsh

Ich hab das jetzt mal auf 'ner FritzBox (mit BusyBox v1.00-pre3) getestet, auch da funktioniert dies problemlos. Was wird denn ausgegeben wenn du z.B.folgendes eingibst
echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta'

mumdigau
04.10.06, 09:28
@suck
Aufruf gem. #8 funktioniert hier ebenfalls. Nur habe ich das Ergebnis nun in einer Datei statt in einer Variablen.

@gmk
Klappt. Nun muß ich das Ergebnis nur noch statt auf die Konsole in eine Variable schreiben.

varneu=$(echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta')

tut's leider nicht, da fehlen wieder die Leerzeichen.

mumdigau

gmk
04.10.06, 12:54
@gmk
Klappt. Nun muß ich das Ergebnis nur noch statt auf die Konsole in eine Variable schreiben.

varneu=$(echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta')

tut's leider nicht, da fehlen wieder die Leerzeichen.
Hast du denn vorher IFS gesetzt?

IFS=$'\n'
varneu=$(echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta')

mumdigau
04.10.06, 15:39
Hast du denn vorher IFS gesetzt?

IFS=$'\n'
varneu=$(echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta')

Nein. Mit dem Setzen des IFS klappt jetzt alles wie gewünscht. Vielen Dank nochmals an alle Helfer.

mumdigau

mumdigau
04.10.06, 22:28
Bei obiger Lösung gibt es noch einen kleinen Schönheitsfehler:

Nach Setzen von IFS auf $'\n' und anschließendem Einfügen der Leerzeilen muß erst mit echo >> in die Datei geschrieben werden, bevor IFS zurückgesetzt werden kann. Andernfalls kommen die zusätzlichen Leerzeichen in der Datei nicht an. Lasse ich aber IFS auf $'\n', wird in der Datei 'n' durch ' ' (0x20) ersetzt. Gibt es eine Möglichkeit, dies zu vermeiden?

mumdigau

suck
04.10.06, 22:53
Ich kann dir nicht ganz folgen. Ich versteh das jetztso, dass nach dem "echo $var >> datei" alle Buchstaben "n" in der Datei zu einem nicht darstellbarem Zeichen werden. Aus "dennoch" würde also "deoch". Könntest du das anhand eines Beispiels erklären.

mumdigau
04.10.06, 23:21
Ich kann dir nicht ganz folgen. Ich versteh das jetztso, dass nach dem "echo $var >> datei" alle Buchstaben "n" in der Datei zu einem nicht darstellbarem Zeichen werden. Aus "dennoch" würde also "deoch". Könntest du das anhand eines Beispiels erklären.

Du liegst fast richtig.

Beispiel: Enthält $var den Wert 'Köln', kommt in der der Datei 'Köl ' an. Anstelle von 'n' steht in der Datei ' ' (0x20).

Zum Anfang des Scripts habe ich mir den aktuellen IFS gesichert. Vor dem Auffüllen mit Leerzeichen setze ich IFS auf $'\n', schreibe anschließend in die Datei und setze dann IFS wieder auf den alten Wert zurück. Würde ich IFS nach var=$(echo $var |sed ':a;s/^.\{1,7\}$/ &/;ta'), aber vor dem Schreiben in die Datei zurücksetzen, kämen die Leerzeichen nicht in der Datei an.

mumdigau

suck
04.10.06, 23:27
Jetzt hab ich es: Du schreibst
IFS="$'\n'"Es muss aber lauten:
IFS=$'\n'Hab ich recht?

mumdigau
04.10.06, 23:35
Jetzt hab ich es: Du schreibst
IFS="$'\n'"Es muss aber lauten:
IFS=$'\n'Hab ich recht?

Leider nein. Die Befehle im Script sehen wie folgt aus:

OLD_IFS=$IFS # aktuellen IFS sichern
IFS=$'\n' # neuen IFS setzen
IFS=$OLD_IFS # IFS zurücksetzen

mumdigau

suck
04.10.06, 23:37
Nächster Versuch:
IFS="" # neuen IFS setzen

mumdigau
04.10.06, 23:49
Nächster Versuch:
IFS="" # neuen IFS setzen

Hat im Schnelltest funktioniert! Ich teste jetzt noch einmal etwas gründlicher um festzustellen, ob möglicherweise andere Nebeneffekte auftreten.

Danke auf jeden Fall.

mumdigau