staging.inyokaproject.org

Wie bringe ich eine for-Schleife dazu, nach dem ersten Treffer von vorn zu beginnen?

Status: Gelöst | Ubuntu-Version: Ubuntu MATE 18.04 (Bionic Beaver)
Antworten |

wxpte

Avatar von wxpte

Anmeldungsdatum:
20. Januar 2007

Beiträge: Zähle...

Liebe Community,

vor drei Jahren hatte ich hier ein Skript eingestellt, das bisher auch problemlos funktioniert hat (den Code habe ich in dem dortigen Beitrag hinterlegt). Nun habe ich es mit der aktuellen Shell-Version in Ubuntu 18.04 nochmals durchgeführt, und musste leider eine böse Überraschung erleben:

Zeile 30: break: nur in einer Schleife mit »for«, »while« oder »until« sinnvoll.

Einige Versuche habe ich unternommen, das Problem zu umgehen:

  • Ich habe das break aus der Function entfernt und in jede Case-Verzweigung als Befehl hinzugefügt

  • Ich habe versucht, die gesamte Function in die for-Schleife zu integrieren

Egal, wie ich das break positioniere, es kommen immer nur zwei verschiedene Ergebnisse:

  1. Trotz der Break-Anweisung wird die Schleife nach dem ersten Treffer stur weiter durchgezählt

  2. Das Skript landet in einer Endlosschleife und muss mit Strg + C abgebrochen werden

Mir gehen langsam die Ideen aus. Hat jemand eine Idee, wie ich das Skript so umbaue, dass es auch nach der Änderung der bash wie gewohnt funktioniert?

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7529

Wundert mich, dass das mal funktioniert haben soll...

Mal naiv das in einen Exitcode gewandelt.

 			echo $(echo $a | cut -f1-3 -d\.).$untergrenze/$bitmaske
 			ip_anzahl=$((ip_anzahl-netzhosts))
 			untergrenze=$((untergrenze+netzhosts))
-			break
+			return 0
 		fi
 	fi
+	return 1
 }	
 while [ $ip_anzahl -gt 1 ] 
 do
 	for bitmaske in {24..32}
 	do
 		case $bitmaske in
-			24)	subnetberechnung
+			24)	subnetberechnung && break
 				;;
-			25)	subnetberechnung
+			25)	subnetberechnung && break
 				;;
-			26)	subnetberechnung
+			26)	subnetberechnung && break
 				;;
-			27)	subnetberechnung
+			27)	subnetberechnung && break
 				;;
-			28)	subnetberechnung
+			28)	subnetberechnung && break
 				;;
-			29)	subnetberechnung
+			29)	subnetberechnung && break
 				;;
-			30)	subnetberechnung
+			30)	subnetberechnung && break
 				;;
-			31)	subnetberechnung
+			31)	subnetberechnung && break
 				;;
 			32)	netzhosts=$((2 ** (32-$bitmaske)))
 				if [ $ip_anzahl -ge $netzhosts ]

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 10978

Mit Python tut man sich da IMHO deutlich leichter:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/usr/bin/env python3
import ipaddress
import sys

if len(sys.argv) != 3:
    sys.exit(f"usage: {sys.argv[0]} IP1 IP2")

ip_addresses = []
for ip_str in sys.argv[1:]:
    try:
        ip_addresses.append(ipaddress.IPv4Address(ip_str))
    except AddressValueError:
        sys.exit(f"{ip_str} is no valid IPv4 address")

for ip_range in ipaddress.summarize_address_range(min(ip_addresses), max(ip_addresses)):
    print(ip_range)

Statt dem Bindestrich für Werte im letzten Oktett erwartet das Skript einfach zwei IPv4-Addressen:

./ip_range.py 85.27.30.20 85.27.30.200
85.27.30.20/30
85.27.30.24/29
85.27.30.32/27
85.27.30.64/26
85.27.30.128/26
85.27.30.192/29
85.27.30.200/32 

Und das funktioniert auch für mehr als ein Oktett ☺

wxpte

(Themenstarter)
Avatar von wxpte

Anmeldungsdatum:
20. Januar 2007

Beiträge: 1004

frostschutz schrieb:

Wundert mich, dass das mal funktioniert haben soll...

Ja, bei Ubuntu 14.04 und 16.04 hat das noch so funktioniert

Mal naiv das in einen Exitcode gewandelt.

... und das funktioniert auch wieder bei Ubuntu 18.04. Das heißt also, dass die Anweisung break jetzt in die Schleife integriert werden muss, aber nur ausgeführt werden darf, wenn die Bedingung in der Funktion zutrifft. Versuchsweise hatte ich vorher schon einmal die Anweisung subnetberechnung; break in die Case-Verzweigungen eingefügt; aber das ist wohl falsch – egal, ob mit oder ohne Exitcode.

Danke für den Tipp. Mit Exitcodes muss ich mich wohl noch ein wenig ausführlicher beschäftigen, um da richtig durchzusteigen. 😉

seahawk1986 schrieb:

Mit Python tut man sich da IMHO deutlich leichter:

Das kann ich mir vorstellen. Der Code sieht für das, was er leistet, recht kompakt aus. Nur kenne ich mich mit Python leider überhaupt nicht aus, ich müsste die Sprache also erst von Grund auf lernen. Da sich das, was ich hauptsächlich skripte, eher im Bereich grep, sed und cut bewegt, war ich bisher davon ausgegangen, dass ich meine Kenntnisse eher in Richtung awk odeer perl erweitern sollte.

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6234

Nur mal eine kleine Anmerkung von mir. Ich beziehe mich dabei auf die Überschrift (den Programmcode hebe ich jetzt nicht durchgearbeitet).

Eine for-Schleife von vorne zu beginnen ist nicht vorgesehen. Aber Du kannst an deren Ende weiter machen, wo dann die Laufvariable modifiziert wird bevor wieder am Anfang weiter gemacht wird. Der Befehl dazu lautet:

continue

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7529

wxpte schrieb:

Versuchsweise hatte ich vorher schon einmal die Anweisung subnetberechnung; break in die Case-Verzweigungen eingefügt; aber das ist wohl falsch – egal, ob mit oder ohne Exitcode.

Dieses Break wird dann halt immer ausgeführt, egal ob Treffer oder nicht.

Was du an deinem Script noch vereinfachen könntest, wär die ganze Switch Anweisung.

Denn eigentlich ist das ja nur ein Case in deinem Switch. Da kannst du entweder mit switch fallthrough diese cases in einen zusammenfassen (und dann auch auf die Subroutine verzichten), oder was ganz anderes machen (if-else statt switch) denn switch lohnt sich ja eigentlich nur wenn man deutlich mehr als 2 unterschiedliche cases hat....

Der Code sieht für das, was er leistet, recht kompakt aus.

Python hat da eben die passende Library für. Wenns eine Standard-Binary für die Linux CLI gibt (hab ich gerade nicht parat) ist es da ja auch nur noch eine Zeile. 😉

wxpte

(Themenstarter)
Avatar von wxpte

Anmeldungsdatum:
20. Januar 2007

Beiträge: 1004

frostschutz schrieb:

Denn eigentlich ist das ja nur ein Case in deinem Switch. Da kannst du entweder mit switch fallthrough diese cases in einen zusammenfassen (und dann auch auf die Subroutine verzichten), oder was ganz anderes machen (if-else statt switch) denn switch lohnt sich ja eigentlich nur wenn man deutlich mehr als 2 unterschiedliche cases hat....

Gedacht habe ich mir so etwas schon; jedoch habe ich es bisher nicht geschafft, das Skript mit einer simplen if-else-Verzweigung dazu zu bringen, so lange weiterzuarbeiten, bis der gesamte Range durch Subnetze abgedeckt ist und dabei auch nur die größtmöglichen Subnetze zu verwenden. Mit switch geht's erstaunlicherweise.

Antworten |