variablen vertauschen

Ale-x

Ale-x

bash lehrling
also ich hab folgenden wunsch
es gibt 2 variablen
a=10
b=20

nun starte ich das programm
./foo a b

danach sieht es so aus
a=20
b=10

ein kollege hat mir schon was fertig gemacht was aber noch nicht so wie es soll funktioniert
er gibt die werte zwar richtig aus aber es tauscht die variablen nicht untereinander aus


und ich hab gar keine ahnung von c und dachte mir könnte jemand hier helfen????
Code:
#include <stdio.h>

int main(int *argc, char *argv[])
{
       if(argc!=3)
       {
               printf("Nicht genug Argumente\n");
               exit(-1);
       }

       char change[1024];
       char save1[1024];
       char save2[1024];

       strcpy(save1,getenv(argv[1]));
       strcpy(save2,getenv(argv[2]));

       // Anzeigen
       printf("%s=%s %s=%s\n",argv[1],getenv(argv[1]),argv[2],getenv(argv[2]));

       // 1. Variable ändern
       setenv(argv[1],save2,1);

       // 2. Variable ändern
       setenv(argv[2],save1,1);

       printf("%s=%s %s=%s\n",argv[1],getenv(argv[1]),argv[2],getenv(argv[2]));
}
 
Dazu benötigst du pointer du kannst sie sonst nicht global ändern
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

void tausche(int *eins, int *zwei) {
int hilf;
hilf = *eins;
*eins = *zwei;
*zwei = hilf;
}
 
Zuletzt bearbeitet:
Das sieht so aus, als möchtest Du den Wert zweier globaler Variablen ändern.

Die gute Nachricht:
Auf den ersten Blick sieht das Programm ganz korrekt aus (bis auf ein paar "Schönheitsfehler"). Und ich bin mir auch ziemlich sicher, das es die Umgebungsvariablen vertauscht.

Die schlechte Nachricht:
Ein Prozess kann, soweit ich informiert bin, nicht die Umgebung seines Elternprozesses ändern. Genaugenommen kann er überhaupt nicht in den Adressraum eines anderen Prozesses greifen, zumindest nicht im User-Mode, ich denke im Kernel-Mode könnte man.
Du kannst bestenfalls wie in Deinem Programm beschrieben die Umgebungsvariablen anpassen und im gleichen Prozess mit dieser Umgebung weiterarbeiten, oder einen neuen Kindprozess starten und mit dieser geänderten Umgebung initialisieren.
Aber falls Du vorhattest dieses Programm z.B. von der Shell ausaufzurufen, oder in einem bash-script zu verwenden, wird nicht der gewünschte Effekt erreicht werden. Die Umgebungsvariablen des Aufrufers ändern sich nicht.

Falls jemand anders weiss wie man sowas erreichen kann - mich würde es auch interessieren.

Um Daten zwischen verschiedenen Prozessen auszutauschen kann man Pipes, Sockets oder Dateien verwenden. Aber ich denke diese Wege sind wohl Overkill für diese Aufgabe, oder?

David
 
@david
also es sollen variablen vertauscht werden die ich selber in einem script vorher festlege


aus diesem script heraus will ich das programm aufrufen zum vertauschen z.b

a=10
b=14
<befehl1>
<befehl2>
./foo a b>
echo a=$a -> ausgabe a=14

./foo soll also die variablen vertauschen
hab jetzt folgendes
Code:
#include <stdio.h>

int main(int *argc, char *argv[])
{
       if(argc!=3)
       {
               printf("Nicht genug Argumente\n");
               exit(-1);
       }

       char save1[1024];
       char save2[1024];

       strncpy(save1, getenv(argv[1]), strlen(getenv(argv[1])) );
       strncpy(save2, getenv(argv[2]), strlen(getenv(argv[2])) );

       // Anzeigen
       printf("%s=%s %s=%s\n",argv[1],getenv(argv[1]),argv[2],getenv(argv[2]));

       // 1. Variable ändern
       setenv(argv[1],save2,1);

       // 2. Variable ändern
       setenv(argv[2],save1,1);

       printf("%s=%s %s=%s\n",argv[1],getenv(argv[1]),argv[2],getenv(argv[2]));
       system("/bin/bash");
       return(0);
}

EDIT: also es funktioniert man muss nur vorher die variablen exportieren dann funktioniert es
die .bashrc wird wohl nochmal aufgerufen vielleicht hat noch jemand eine idee wie man das anders machen kann
 
Zuletzt bearbeitet:
Ein Moment mal .... imho bekommen prozesse immer kopien der umgebungsvariablen, daher können sie nicht die Umgebung des Elternprozesses ändern. kann es sein, das du folgendermaßen vorgehst:
1. wahrscheinlich führst du dieses skript aus:
Code:
a=10
b=14
<befehl1>
<befehl2>
./foo a b
und wenn es durchgelaufen ist gibst du diesen Befehl ein:
echo a=$a -> ausgabe a=14
Wenn das so ist, dann verstehe ich warum das bei Dir "funktioniert". Das tut nämlich nur so. Aber wenn Du damit zufrieden bist, dann ist ja alles in Ordnung. Aber ich glaube Du solltest mal ein shell-script schreiben, das so alles erledigt:
Code:
a=10
b=14
export a
export b
./foo a b
echo a=$a
echo b=$b
Ich denke wenn Du dieses Skript ausführst, wird das Ergebnis nicht Deinen Wünschen entsprechen.
Ich hab leider grad keine Zeit, da ich noch einen Termin habe. Aber melde Dich nochmal, wenn Du das ausprobiert hast und erzähl mal ob ich recht hatte. Saug mir mangels Zeit nämlich grad aus den Fingern. Dann erklär ich Dir auch warum das so ist.
 
also so in der shell funktionierts
[root@jacque tools]# a=10
[root@jacque tools]# b=20
[root@jacque tools]# ./a a b
a=10 b=20
a=20 b=10
[root@jacque tools]# echo $a
20


im script nicht
 
Du sagst im Skript nicht. Hmmm, ich nehme mal an, das ist nicht gerade das, was ich eine detailierte Fehlerbeschreibung nennen würde. Aber ich kann mir auch so denken was passiert.... Wenn du das als Skript verwendest, werden wahrscheinlich nicht einmal die Ausgaben am Ende des Programmes stattfinden richtig?

Das Problem liegt darin, wie Dir mit dem obigen Programm vorgespielt wird, das Umgebungsvariablen verändert wurden. Also ich erzähl mal Schritt für Schritt was da passiert. Wir nehmen den ersten Fall, du tippst alle Befehle in die bash ein. Das läuft so ab:
  1. Du setzt die Umgebungsvariablen a und b
  2. Du startest das Tausch-Programm und übergibst ihm die Namen der zu vertauschenden Variablen. Das Programm wird in einem neuen Prozess, als Kindprozess Deiner Bash gestartet.
  3. Im Tauschprogramm werden nun die Inhalte der beiden Umgebungsvariablen vertauscht. Dies geschieht aber in der Umgebung des Tauschprogramms, nicht in der Umgebung des Elternprozess.
  4. Jetzt kommt der fiese Trick/Fehler in dem Programm. Mit dem Befehl
    Code:
    system("/bin/bash");
    startest Du eine weitere Bash. Diese ist nun ein Kindprozess des Tauschprogramms und kopiert die Umgebung des Tauschprogramms. In dieser Umgebung befinden sich nun ebenfalls die vertauschten Variablen.
  5. In dieser neuen Bash gibst Du nun die echo-Befehle ein, die Dir den Inhalt der Umgebungsvariablen a und b ausgeben. Dieser Inhalt ist tatsächlich vertauscht. Aber bedenke: Wir befinden uns bereits im Kind-Kind-Prozess der ursprünglichen Shell. Und zur Zeit laufen immer noch alle 3 Prozesse! Und die Variablen a und b die Du hier abfragst sind schon lange nicht mehr die ursprünglichen die Du vertauschen wolltest.
Dir ist das mit der neuen Bash wahrscheinlich aus dem Grund nicht aufgefallen, weil sie im selben Fenster läuft wie die ursprüngliche. Aber Du kannst das schnell überprüfen, indem Du die oben genannten Schritte noch einmal durchführst und dann beginnst die Prozesse Schritt für Schritt zu beenden. Also nachdem Du das "positive" Ergebnis gesehen hast, gibst Du einmal "exit" ein. Die Kind-Kind-Shell wird beendet. Aber was ist das?! Das Fenster ist noch auf!

Richtig, denn nach dem der "system("/bin/bash")"-Befehl nun endlich zurückgekehrt ist, kann das Tauschprogramm fortfahren. Naja, witzig wäre wenn ich noch ein paar printf's wären, die ausgaben würdest du nämlich jetzt erst bekommen. Aber das Programm beendet sich jetzt mit "return 0". Damit ist jetzt auch der letzte Kindprozess beendet. Die Beendigung dieses Prozesses hast Du aber auf dem Bildschirm nicht mitbekommen.

Jedenfalls sind wir nun endlich in der "richtigen" also der ursrünglichen Bash angekommen. Frage doch jetzt nochmal per echo den Inhalt der Variablen ab! Jetzt sollte zu sehen sein, daß sie sich in Wahrheit nicht verändert haben und jede ihren ursprünglichen Wert besitzt.

Puh! Muss ich jetzt noch erklären warum das Skript Dir das alles nicht vorgaukelt?

Ok, ganz kurz, ich nehme an, jetzt sollte es ohnehin schon klar sein.

Also Du startest eine Bash (1. Prozess). Du startest das Skript(2.). Das skript startet das Programm(3. Proc). Im 3. Proc werden die Variablen vertauscht. Bisher gibt es nicht mal eine Ausgabe auf der Console. Das Programm startet eine neue Bash. Die neue Bash wartet auf deine Eingabe! An dieser Stelle dachtest Du wahrscheinlich, das Skript sei zu Ende und es wäre überhaupt nichts passiert, denn auf der Console gibt es bislang noch keine Ausgaben.

Irrtum! Beweis: Gib "exit" ein. Die Bash wird beendet. Das Programm wird beendet. (Damit ist die letzte Umgebung verschwunden in der die Variablen vertauscht waren). Wir befinden uns jetzt wieder im Skript-Prozess. Dieser gibt nun die Variablen aus, die sich nicht verändert haben. Dann beendet sich der skript prozess und wir sind in der ursprünglichen Bash. Falls die Variablen erst im Skript erzeugt und mit "export" zu Umgebungsvariablen wurden, dann sind sie jetzt nicht einmal mehr vorhanden, was leicht mit echo nachzuprüfen ist.

Ok, damit sollte alles klar sein.

Wozu brauchst Du das überhaupt? Ich meine das geht mit Bash-Boardmitteln doch viel einfacher! Sowas ist schneller geschrieben, genau genommen innerhalb von 45 Sekunden, wenn man echt langsam ist, und ist auch schneller in der Performance, da keine neuen Prozesse gestartet werden müssen. Wenn es echt nur um das Vertauschen zweier Variablen innerhalb des Skripts geht, dann macht man das so:
Code:
# Initialisierung
a=14
b=10
# Vertauschung
tmp=$b
b=$a
a=$tmp
Wenn es Dir darum geht, diesen kurzen Programmcode nicht überall im skript zu wiederholen, da er häufig vorkommt, dann schreib Dir doch eine Funktion/Makro. Syntax dazu findest Du hier: http://www.ss64.com/bash/function.html

Ich hoffe das hilft Dir weiter.

Ein Prozess kann und sollte auch nicht in dem Adressraum (Speicherbereich) eines anderen herumfuhrwerken.

PS: Liest man solange Postings überhaupt?
:schlaf:
 

Ähnliche Themen

Unix Webserver mit HTML Seite erstellen

ip6tables Problem

[gelöst] - for file in ... nur für bestimmte Endungen?

Ausführbare C-Datei von Mac OS auf Embedded Linux ausführen

Prozesskommunikation mit PIPES - wie funktioniert das?

Zurück
Oben