PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeilen auskommentieren



peso7
21-02-2008, 19:40
Hallo

Wer kann helfen?
Ich brauche zwei Shell-Skripte, die folgendes macht:
- es gibt eine Datei "ip-adr" mit IP-Adressen (zeilenweise)
- es gibt eine Datei "ip-adr_ausschluss" mit IP-Adressen (zeilenweise)
- das Skript "ausschliessen" soll in der Datei "ip-adr" bei jeder IP-Adresse am Anfang der Zeile das Zeichen "#" zum auskommentieren einfügen, deren IP-Adresse in "ip-adr_ausschluss" vorkommt. Die anderen Zeilen soll unangetastet bleiben.
- das zweite Skript "einschliessen" soll in der Datei "ip-adr" bei jeder IP-Adresse, die am Anfang der Zeile das Zeichen "#" zum auskommentieren hat, das "#" entfernen, wenn die IP-Adresse in "ip-adr_ausschluss" vorkommt. Die anderen Zeilen soll unangetastet bleiben. (Langer Rede kurzer Sinn: die oben auskommentierten IP-Adressen wieder reaktivieren.)

Kann mir jemand verraten, wie das elegant (und verständlich, ich will ja was lernen) gelöst werden kann?

Danke, Peter

ContainerDriver
21-02-2008, 23:59
Hallo.

Ich hab folgendes gebastelt:


#!/bin/sh
FILE_IP_ADDR="ip-addr"
FILE_IP_ADDR_BLOCK="ip-addr_ausschluss"

case "$1" in
block)
sed 's/.*/s\/^ *\0\/#\\0\//' $FILE_IP_ADDR_BLOCK|sed -i -f - $FILE_IP_ADDR
;;
unblock)
sed 's/.*/\/^ *# *\0\/s\/#\/\//' $FILE_IP_ADDR_BLOCK|sed -i -f - $FILE_IP_ADDR
;;
*)
echo "Argument muss block oder unblock sein.";
exit 1;
;;
esac;
.

Wenn du alle IPs, die in $FILE_IP_ADDR_BLOCK gelistet sind, in $FILE_IP_ADDR auskommentieren willst, dann musst du das Skript mit dem Argument "block" aufrufen; zum Kommentare entfernen wäre der Aufruf mit dem Argument "unblock".

Die Funktionsweise für block ist die folgende: links von der Pipe wird ein sed-Skript der Form


s/^ *$IP_AUS_FILE_IP_ADDR_BLOCK/#$MATCH_DES_VORHERIGEN_REGEXP/

generiert . Das wird an das folgende sed auf der rechten Seite der Pipe weitergereicht, das einfach das Skript auf $FILE_IP_ADDR anwendet.

Gruß, Florian

peso7
22-02-2008, 20:32
Hallo Florian

Danke für die Unterstützung.
Ich bekomme aber leider eine Fehlermeldung, dass die Option -i nicht unterstützt werde (sed Version 3.02) und das Skript bricht ab.
Gibts einen Workaround auf Skript-Ebene (kann sed nicht updaten)?

Alles Gute, Peter

ContainerDriver
23-02-2008, 00:28
Hallo Peter,

das -i bewirkt, dass Änderungen direkt in die Eingabedatei geschrieben werden:


-i[SUFFIX], --in-place[=SUFFIX]

edit files in place (makes backup if extension supplied)
.

Findest du vielleicht eine äquivalente Option für dein sed in der Manpage? Ansonsten wird man wohl nicht um eine temporäre Datei rumkommen....

Da müsste man dann das -i weglassen, die Ausgabe des letzten sed in eine temporäre Datei umlenken (deren Dateinamen am besten ein $$ (= aktuelle PID) enthält) und dann im nächsten Schritt die temp. Datei an die Stelle der alten $FILE_IP_ADDR kopieren.

Gruß, Florian

peso7
23-02-2008, 08:13
Hallo Florian

Das habe ich gemacht mit:


sed 's/.*/s\/^ *\0\/#\\0\//' $FILE_IP_ADDR_BLOCK|sed -f - $FILE_IP_ADDR > temp
mv temp $FILE_IP_ADDR

Funkionert bestens.

Nun taucht aber nochmals ein Problem auf.
In der Variante "block" bekommt jede Zeile von $FILE_IP_ADDR ein "#" und die Zeilen, die auskommentiert werden sollen, bekommen ein "##" vorneweg - also schlichtweg ein "#" zuviel. Jetzt könnte ich einfach jeder Zeile das erste Zeichen wieder wegschneiden, aber die Korrekturmöglichkeit besteht wohl auch in "s/.*/s\/^ *\0\/#\\0\//' $FILE_IP_ADDR_BLOCK" (was ich nicht wirklich durchschaue...), oder?

Alles Gute, Peter

ContainerDriver
23-02-2008, 11:24
Mmmh, das ist ja seltsam...



sed 's/.*/s\/^ *\0\/#\\0\//' $FILE_IP_ADDR_BLOCK

sollte eigentlich alle Zeilen (der reguläre Ausdruck ".*" passt auf alles) in der Eingabedatei mit einem # versehen; gleichzeitig schreibt der Befehle auf die Standardausgabe ein "s/^ *$IP_ZUM_AUSKOMMENTIEREN/#\0/" was dann auf die Datei $FILE_IP_ADDR angewendet wird. "s" heißt ersetze alle Zeilen, auf die der reguläre Ausdruck "^ *$IP_ZUM_AUSKOMMENTIEREN" passt (^ ist der Zeilenanfang, dann beliebig viele Leerzeichen und dann eine IP-Adresse aus der Ausschlussliste) mit einem "#\0" (\0 ist der String, auf den der vorherige reguläre Ausdruck gepasst hat).

Kannst du vielleicht mal die Ausgabe von


sed 's/.*/s\/^ *\0\/#\\0\//' ip-addr_ausschluss

posten (am besten mal auch ein -r hinter das sed setzen, also "sed -r ...")?

Bei mir sieht die so aus:


florian@leuchtturm1:~/tmp$ sed 's/.*/s\/^ *\0\/#\\0\//' ip-addr_ausschluss
s/^ *127.0.0.5/#\0/
s/^ *127.0.0.2/#\0/


Gruß, Florian

jan61
24-02-2008, 18:05
Moin,


...Nun taucht aber nochmals ein Problem auf.
In der Variante "block" bekommt jede Zeile von $FILE_IP_ADDR ein "#" und die Zeilen, die auskommentiert werden sollen, bekommen ein "##" vorneweg - also schlichtweg ein "#" zuviel.

ich habe den Code von ContainerDriver mal mit einem alten sed in Version 3.02 durchgespielt (lag zufälligerweise noch auf einer meiner Kisten rum) - funktioniert mit Ausnahme der -i-Option so wie es sollte. Kann es sein, dass Du Dir bei den Experimenten die ip-addr oder ip-addr_ausschluss zerschossen hast?

Noch eine Bemerkung zum Ersetzen der Ausgangsdatei. Benutze lieber einen anderen Mechanismus, das was Du da probierst, hat entscheidende Nachteile:
1. Wenn eine Datei tmp existiert, überschreibst Du die gnadenlos.
2. Wenn tmp existiert und Du keine Schreibrechte hast, wird sie zwar nicht überschrieben, aber anschließend der Inhalt von ip-addr ohne Rückfrage mit dem (wie auch immer gearteten) von tmp überschrieben.
3. Wenn das Ersetzen aus irgendeinem Grund schief geht, hast Du anschließend eine leere Datei tmp und überschreibst damit Deine ip-addr.

Also 2 Regeln:
- benutze einen eindeutigen Namen für die temp. Datei
- Überschreibe ip-addr nur dann, wenn das Ersetzen geklappt hat.


TMP_FILE=`mktemp $$.XXXXXX`
sed ... $IP_ADDR >$TMP_FILE && mv $TMP_FILE $IP_ADDRMan muss noch ein paar Sachen zusätzlich abprüfen (mktemp kann schiefgehen, der mv kann schiefgehen).

Jan

peso7
27-02-2008, 21:16
Hallo Florian

Ich war etwas "offline".

Danke für den Tipp.
Bei mir gibt sed 's/.*/s\/^ *\0\/#\\0\//' ip-addr_ausschluss noch eine "dritte" Zeile.


s/^ *127.0.0.5/#\0/
s/^ *127.0.0.2/#\0/
s/^ */#\0/

Diese ist wohl für das zusätzliche "#" am Anfang jeder Zeile zuständig.

Etwas Nachforschen hat ergeben, dass es in ip-addr_ausschluss am Schluss eine zusätzliche Leerzeile hat. Die habe ich in meinen Editor übersehen!

Jetzt ist alles OK.

Danke für die Unterstützung.

Alles Gute, Peter

ContainerDriver
27-02-2008, 21:53
Hallo.


Hallo Florian

Ich war etwas "offline".

Danke für den Tipp.
Bei mir gibt sed 's/.*/s\/^ *\0\/#\\0\//' ip-addr_ausschluss noch eine "dritte" Zeile.


s/^ *127.0.0.5/#\0/
s/^ *127.0.0.2/#\0/
s/^ */#\0/

Diese ist wohl für das zusätzliche "#" am Anfang jeder Zeile zuständig.

Etwas Nachforschen hat ergeben, dass es in ip-addr_ausschluss am Schluss eine zusätzliche Leerzeile hat. Die habe ich in meinen Editor übersehen!


Oha, stimmt, ".*" passt auch auf die Leerzeile. Blöder Fehler.
Wenn du Leerzeilen erlauben willst, könntest du im Skript das ".*" durch ein "[^ ]+" austauschen (mindestens ein nicht Leerzeichen), allerdings braucht dann sed scheinbar die Option -r.
Jetzt ist mir übrigens noch ein Fehler aufgefallen:


florian@leuchtturm1:~/tmp$ cat ip-addr
127.0.0.1
127.0.0.21
127.0.1.2
127.0.0.3
127.0.0.4
127.0.0.5
florian@leuchtturm1:~/tmp$ ./ausschliessen.sh block
florian@leuchtturm1:~/tmp$ cat ip-addr
127.0.0.1
# 127.0.0.21
127.0.1.2
127.0.0.3
127.0.0.4
#127.0.0.5
florian@leuchtturm1:~/tmp$ cat ip-addr_ausschluss
127.0.0.5
127.0.0.2

127.1.1.3
, d.h. in diesem Fall wird auch 127.0.0.21 auskommentiert, obwohl nur 127.0.0.2 in der Liste der auszuschließenden IPs steht.

Also hier mal ein kleines Update:


#!/bin/sh
FILE_IP_ADDR="ip-addr"
FILE_IP_ADDR_BLOCK="ip-addr_ausschluss"

case "$1" in
block)
sed -r 's/[^ ]+/s\/^ *\0 *$\/#\\0\//' $FILE_IP_ADDR_BLOCK|sed -i -f - $FILE_IP_ADDR
;;
unblock)
sed -r 's/[^ ]+/\/^ *# *\0 *$\/s\/#\/\//' $FILE_IP_ADDR_BLOCK|sed -i -f - $FILE_IP_ADDR
;;
*)
echo "Argument muss block oder unblock sein.";
exit 1;
;;
esac;
.

Gruß, Florian