Zum Inhalt springen

Bashscript: 1. Buchstabe in neue Variable


Noxy

Empfohlene Beiträge

Hi

Ich schreibe grad ein Shell Script und hab das Problem, dass ich eine Variable habe, deren Inhalt z.B. "Test" ist.

Jetzt brauche ich den ersten Buchstaben, also das "T" in einer neuen Variable. Wie schaut das Script dazu aus?

Danke für alle Hilfe.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo,

ich hoffe, folgendes Konstrukt hilft dir etwas weiter...


var=Test


var=$(expr "$var" : '\([[:alnum:].:,;_+@?%&=#\/]\)')


echo $var

bzw. ganz verkürzt als debug zum Nachvollziehen und Testen:

var=Test; echo var=$(expr "$var" : '\([[:alnum:].:,;_+@?%&=#\/]\)')

jetzt kannst du var mal ändern...es wird immer nur das erste Zeichen ausgegeben bzw. nach $var gespeichert.... TIPP: Mach aber vor dem expr...noch eine Abprüfung dazu a la 'test -n', dass die variable $var...also die Erste, in der "Test" steht...nicht leer sein darf.... sowas hier:

var=Test;


test -n $var && {

    var=$(expr "$var" : '\([[:alnum:].:,;_+@?%&=#\/]\)')

} || echo "Error: '$var' leer => exit"; exit 1

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich hab noch ein Problem vielleicht weiss jemand noch was dazu:

Ich lese aus einer Datei etwas aus mit:

test=`grep Name: /tmp/test.txt | awk '{print$2}'`

dann eine if Bedingung:

if [ "$test" = "Bla" ]

then

echo "Ja"

fi

Aber die Bedinung wird nicht erfüllt, auch wenn in $test "Bla" steht, wenn ich echo $test mache, wird "Bla" ausgegeben. Kann es sein, dass irgendein unsichtbares Formatierungszeichen noch mit dabei steht oder mache ich irgendwas falsch?

Edit: Das Scipt vorher funktioniert, danke!!

Link zu diesem Kommentar
Auf anderen Seiten teilen

Original geschrieben von Noxy

Aber die Bedinung wird nicht erfüllt, auch wenn in $test "Bla" steht, wenn ich echo $test mache, wird "Bla" ausgegeben. Kann es sein, dass irgendein unsichtbares Formatierungszeichen noch mit dabei steht oder mache ich irgendwas falsch?

Hallo,

was steht denn in der /tmp/test.txt drinnen, steht dort öfters Name: oder nur einmal..., ist zwischen

Name: und Bla ein Leerzeichen, oder nicht?

Warum probierst du es nicht mal so:


test=$(cat /tmp/test.txt | awk -FName: '{print$2}')


Und die IF-Anweisung:


if test "$test" = "Bla"; then

    echo "Ja";

else

    echo "Nein";

fi

Also es kommt jetzt ganz auf den Anwendungsfall drauf an....wenn du den Aufbau der /tmp/test.txt

posten magst könnt ich dir eventl. besser weiterhelfen ;)

PS: Obiges Konstrukt (also nur die IF-Abfrage) funktioniert nicht (bzw. liefert immer 'Nein'), falls in der test.txt mehrere 'Name:' drinnen stehen....

Link zu diesem Kommentar
Auf anderen Seiten teilen

Original geschrieben von Schlaubi

Hallo,

was steht denn in der /tmp/test.txt drinnen, steht dort öfters Name: oder nur einmal..., ist zwischen

Name: und Bla ein Leerzeichen, oder nicht?

Also es kommt jetzt ganz auf den Anwendungsfall drauf an....wenn du den Aufbau der /tmp/test.txt

posten magst könnt ich dir eventl. besser weiterhelfen ;)

Also eigentlich geht es um folgendes:

Ich will von einem Rechner eine Mail an eine Linuxkiste schicken und wenn eine Mail da ist, werden verschiedene Sachen ausgelöst. In der Mail steht dann sowas wie

Name: Bla

Befehl: Irgendwas

drin. Jetzt möchte ich wenn der Name oder der Befehl ein spezielles Wort sind eine Aktion auslösen. Leider führt er die if-Schleife immernoch nicht aus.

Link zu diesem Kommentar
Auf anderen Seiten teilen

dann versuch doch mal diese If-Abfrage...


if [ "$test" = " Bla" ]

then

echo "Ja"

fi

Also mit blank (leerzeichen) vor dem Wort Bla und wenn die dann "Ja" ausgibt,

dann weißt du ja, wo der Fehler liegt oder? ;)

PS: Kann es sein, dass du den einen Vorschlag von mir a la "awk -FName:" noch nicht ausprobiert hast? (Achtung wenn du das versuchst, dann muss auch die If-Abfrage so bleiben wie sie ist, also ohne blank am Anfang des Strings...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Arks ich dreh echt gleich durch, jedesmal wenn ich eine Variable verwenden will, die ich aus der Mail gezogen hab gibt es Probleme. Gibt es eine Möglichkeit die Variablen so neu zu schreiben, dass nur die Textinformation erhalten bleibt und alle eventuell enthaltenen anderen Zeichen verschwinden?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo,

versuch folgendes mal:


#! /bin/bash


ls mail* >adminmail.lst


liste=$(cat adminmail.lst)


for z in $liste; do

         befehl=$(cat $z | grep Befehl: | awk '{ print $2 }');

           name=$(cat $z | grep Benutzer: | awk '{ print $2 }');

    firstletter=$(expr "$name" : '\([[:alnum:].:,;_+@?%&=#\/]\)');

    echo "'$firstletter'"

    echo "'$befehl'"

    echo "'$name'"


    if test "$befehl" == "Start3"; then

        echo "Funzt";

    else

        echo "So ein Mist";

    fi

done


(PS: ich habe mir vorher 3 Test-E-Mail Dateien angelegt namens "mail1, mail2, mail3"... mit dem Inhalt:

--snip--

Benutzer: user1

Befehl: Start1

--snap--

user1 und Start1 ändert sich von 1-3 je nach Datei....nur zur Info ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke.

Das Script funktioniert wunderbar SOLANGE ich eine selbsterstellte Datei verwende, die die Parameter enthält.

Wenn ich eine richtige Mail verwendet, geht es nicht. Ich glaube ich weiss auch wiso. Zeilen in Mails werden immer mit "newline" beendet und wahrscheinlich ist diese "newline" auch in der Variable mit enthalten und verursacht die Probleme.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe keine Ahnung ob dies der Grund ist, aber warum prüfst du dies nicht einfach nach?

Du muss halt nur das Skript soweit bringen, dass der Output so debuged wird, dass man erkennt, ob eine newline enthalten ist oder nicht z.B. indem du den Output in einfache Hochkomma setzt...

also so:


echo "'$befehl'"

sieht der Output dann nicht so aus (inkl. newline):

'Start1

'

sondern so (ohne newline):

'Start1'

dann kann es daran eigentlich nicht liegen....

Link zu diesem Kommentar
Auf anderen Seiten teilen

Genau wie ich mir gedacht hab:

Ausgabe von od -c

0000000 ' S t a r t 1 \r ' \n

0000013

Ich hab einfach in der Mail aus den 2 Zeilen, 1 Zeile gemacht und dahinter ein Platzhalter-Wort gesetzt.

Befehl: Start1 user1 Platzhalter

Jetzt nehm ich den Benutzer mit awk '{ print $3 } aus der gleichen Zeile heraus und das ganze funktioniert.

Ich werde jetzt erstmal damit weitermachen, wenn jemand noch eine elegantere Lösung einfällt nur her damit.

Vielen Dank an Schlaubi erstmal, mein neuer Bash Gott :)

Edit: Wobei, wenn jemand noch einfällt, wie man das \n wegbekommt wär schön, wenn nicht gehts auch :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Original geschrieben von Noxy

Genau wie ich mir gedacht hab:

Ausgabe von od -c

0000000 ' S t a r t 1 \r ' \n

0000013

Edit: Wobei, wenn jemand noch einfällt, wie man das \n wegbekommt wär schön, wenn nicht gehts auch :)

Hallo,

also ich denke nicht dass das newline (\n) ein Problem darstellt, ich denke eher an das \r (Carriage Return Beschreibung hier)

Merke:

Unix-Format

Auf Rechnern mit dem Betriebssystem UNIX wird die gleiche Zeichen-Codierung (ANSI) wie auf Windows-PCs benutzt. Von UNIX stammende Textdateien sind also prinzipiell in Windows "lesbar". Es gibt aber einen wesentlichen Unterschied im Satzformat:

Auf PCs (DOS, Windows) wird ein Zeilenwechsel (Satzende, Umbruch) durch zwei Steuerzeichen erzeugt:

CR = Carriage-Return (Waagenrücklauf)

und

LF = Line-Feed (Zeilenvorschub).

Unter UNIX reicht eines der Zeichen für den Zeilenwechsel.

hier etwas genauer nachzulesen => selflinux

Ich habe einfach mal versucht deinen Problemfall bei mir nachzustellen um damit herumzuprobieren, guck mal:

Erst habe ich es in eine Datei geschrieben:


echo -ne "Start1\r\n" > x; cat x

Dies bringt zur Ausgabe:

Start1

wenn du jetzt ein od -c dranhängst kannst du erkennen, dass ich das selbe habe wie in deinem Fall also das:

echo -ne "Start1\r\n" > x; od -c x


0000000   S   t   a   r   t   1  \r  \n

0000010

So um deinem Problem ein Stückchen näher zu kommen habe ich es danach noch mit einer Variable versucht...:

var=$(echo -ne "Start1\r\n"); echo "'$var'"

Dies bringt zur Ausgabe:

'Start

Genau wie bei dir oder? :marine So, wenn du dann noch den od -c dranhängst dann weißt auch, dass er den ' zwar hat, aber nicht ausgibt:

var=$(echo -ne "Start1\r\n"); echo "'$var'" | od -c

Siehe Ausgabe:

0000000   '   S   t   a   r   t   1  \r   '  \n

0000012

So um dein Problem jetzt zu beheben müsstest du nur den \r wegbekommen...und das geht ganz easy mit recode (man recode) oder mit dos2unix (man dos2unix), doch leider können die beiden Kommandos das nicht mit Variablen sondern nur mit Files (soweit ich das weiß, bitte nicht schlagen ;) ), deshalb empfehle ich dir hier ganz einfach den guten alten sed... (perl könntest du auch nehmen, aber dass wäre jetzt wieder zu umständlich in deinem Fall) Deshalb hier der Beweis, es können soviele \r vorkommen, egal dich brauchts nicht mehr zu interessieren ;)

var=$(echo -ne "\rSt\rart1\r\n"); echo $var | sed 's/\r//g' | od -c

so und nun taucht auch am Ende wieder das verloren gegangene ' auf und alle sind glücklich ;) Beweis:

var=$(echo -ne "\rSt\rart1\r\n"); var=$(echo $var | sed 's/\r//g'); echo "'$var'"


Ausgabe:


'Start1'

Hier nun nochmal das komplette Skript (weils vielleicht doch etwas unübersichtlich war das alles, ich hoffe ich habe dir nicht nur bei deinem Problem geholfen, sondern du hast noch etwas dazugelernt):

#! /bin/bash


ls mail* >adminmail.lst


liste=$(cat adminmail.lst)


for z in $liste; do


         befehl=$(cat $z | grep Befehl: | awk '{ print $2 }');

         befehl=$(echo $befehl | sed 's/\r//g');

           name=$(cat $z | grep Benutzer: | awk '{ print $2 }');

           name=$(echo $name | sed 's/\r//g');

    firstletter=$(expr "$name" : '\([[:alnum:].:,;_+@?%&=#\/]\)');

    firstletter=$(echo $firstletter | sed 's/\r//g');

    echo "'$firstletter'"

    echo "'$befehl'"

    echo "'$name'"


    if test "$befehl" == "Start3"; then

        echo "Funzt";

    else

        echo "So ein Mist";

    fi

Naja beim Schreiben des Skriptes ist mir aufgefallen, dass es da natürlich noch die andere Möglichkeit gibt und zwar, dass du dir das mit den Variable sparst und einfach doch nur mit dos2unix <filename> die mails ins richtige Format umwandelst also dann so:

#! /bin/bash


ls mail* >adminmail.lst


liste=$(cat adminmail.lst)


for z in $liste; do

    dos2unix --quiet $z;

         befehl=$(cat $z | grep Befehl: | awk '{ print $2 }');

           name=$(cat $z | grep Benutzer: | awk '{ print $2 }');

    firstletter=$(expr "$name" : '\([[:alnum:].:,;_+@?%&=#\/]\)');

    echo "'$firstletter'"

    echo "'$befehl'"

    echo "'$name'"


    if test "$befehl" == "Start3"; then

        echo "Funzt";

    else

        echo "So ein Mist";

    fi

done

Original geschrieben von Noxy

Vielen Dank an Schlaubi erstmal, mein neuer Bash Gott :)

....und danke für die Blumen :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...