Wie lese ich mittels Batch-File (CMD) eine einzelne Zeile aus?
Guten Abend zusammen,
ich möchte mir eine Batch-File schreiben, mit der ich den Namen meines WLAN-Netzwerks (SSID) auslese. Dazu lasse ich mir eine Zusammenfassung der Drahtlosinformationen mittels netsh wlan show all anzeigen. Diesen umfangreichen Text filtere ich nach dem Begriff Status mittels netsh wlan show all | find /N "Status".
Das Ergebnis sind auf meinem System vier Einträge, die exemplarisch wie folgt aussehen:
[64] Status : Verbunden
[79] Status des gehosteten Netzwerks : Nicht verfügbar
[92]Status des gehosteten Netzwerks
[94] Status : Nicht verfügbar
Ich weiß, dass in Zeile 65 der aktive/aktuelle WLAN-Netzwerkname (SSID) hinterlegt ist. Diese sieht folgendermaßen aus:
SSID : FRITZ!Box 7520 SZ
In meinem Fall müsste ich den Text in Zeile 65, der nach einem Leerzeichen nach dem Doppeltpunkt beginnt, extrahieren und in einer Variablen abspeichern.
Ich weiß, dass unter der CMD-Eingabeaufforderung eine Variablenzuweisung nicht nach dem klassischen Prinzip
var = Berechnung
erfolgt, sondern stattdessen eine for-Schleife zu verwenden ist. Mein Ansatz dafür lautet
for /f %%a in ('netsh wlan show all ^|find /N "Status"') do (set "strSSID=%%a")
Jedoch müsste ich die Laufvariable %%a (?) auf 1 begrenzen, weil ich sonst den letzten Eintrag ([94]) abspeichere.
Meine Fragen lauten daher konket:
- Wie limitiere ich die Laufvariable einer for-Schleife?
- Wie lese ich dann die um eins inkremetierte Zeile aus?
- Wie extrahiere ich den Text dieser Zeile nach dem Doppelpunkt sowie dem einen Leerzeichen bis zur EOL und speichere diesen in einer Variable ab?
Ich glaube, dass ich der Lösung schon recht nah bin, aber hier komme ich leider nicht weiter. Ich freue mich, über jeden Hinweis und weitere Hilfe.
Viele Grüße,
Christian
1 Antwort
Ich habe keine Ahnung, weshalb Du mit den Zeilennummern herummurkst? Ich habe kein Wlan n meinem aktuellen Rechner und auch nicht den Output von netsh wlan show all im Kopf, in jedem Fall zu viel Informationen für ein sinnvolles filtern.
netsh wlan show ... lässt sich feiner justieren:
wenn du Dir die für Dein Wlan sichtbaren Netzwerke anzeigen lassen willst:
netsh wlan show networks
der Output sieht dann etwa so aus:
...
SSID 1 : EselhimmelLowBand
Network type : Infrastructure
Authentication : WPA2-Personal
Encryption : CCMP
SSID 2 : EselhimmelHighBand
Network type : Infrastructure
Authentication : WPA2-Personal
Encryption : CCMP
SSID 3 : EselhimmelGast
Network type : Infrastructure
Authentication : WPA2-Personal
Encryption : CCMP
...
mit netsh wlan show networks|find "SSID" filtern wir "senkrecht" alle Zeilen, welche SSID enthalten und übergeben den Output an den for/f-loop und zerlegen die Zeile (waagerecht) an den Trennzeichen (delims) Doppelpunkt und Leerzeichen. Wir Wollen die Token 1,2 und den Rest.
for /f "tokens=1,2*delims=: " %%a in ('netsh wlan show networks^|find "SSID"')do (
echo Token1: %%a
echo Token2: %%b
echo Rest : %%c
rem jetzt wollen wir mal ganz "fies" sein und Variablen basteln:
set "Meine.%%a.%%b.=%%c"
)
rem mal alle variablen, die mit "Meine." beginnen, anzeigen
set "Meine."
pause
so kann man (fast) jede Zeile zerlegen. Output eines Befehls anschauen überlegen wie man "senkrecht" filtert, überlegen welche Token man aus den Gefilterten Zeilen man braucht und durch welch Trennzeichen (delims)diese getrennt sind. Mehrere aufeinanderfolgende Trennzeichen werden als einzelnes erkannt. (diese werden "gefressen"!) definierte Trennzeichen werden im Rest-Token * nicht ausgewertet und bleiben erhalten.
for /f "tokens=1,2*delims=[]: " %%a in ("[666] :ich bin ein [blub]: text lala la")do (
echo Token1: %%a
echo Token2: %%b
echo Rest : %%c
)
Wie limitiere ich die Laufvariable einer for-Schleife?
Wie lese ich dann die um eins inkrementierte Zeile aus?
die Sache mit den Zeilennummern und inkrementieren solltest Du Dir aus dem Kopf schlagen. das braucht Konstruktionen "aus den tiefsten Herzen der Hölle". Der Body eines for/f-Loops kennt nur die aktuell übergebene Zeile und weiß von nichts, was nicht übergeben wurde oder vorher war.
- bleibt nur nochmal lesen und neu Nummerieren und mit der dem IncrementWert selektieren
- aus einer schleife kann man herausspringen... wenn man hat was man wollte
Ansatz...
demo.txt
laberrhababer
laberrhababer
die will ich spaeter, wenn nächste huhu enthält
blubb :mizekatz
blubb mit was anderem : nicht lustig
laberrhababer
laberrhababer
die will ich spaeter, wenn naechste huhu enthaelt
blubb :huhu
blubb mit was anderem : nicht lustig
laberrhababer
laberrhababer
die will ich nicht mehr, ich habe schon ein huhu
blubb :huhu
blubb mit was anderem : auch nicht lustig
laberrhababer
laberrhababer
laberrhababer
demo.cmd
@echo off
setlocal enableDelayedExpansion
rem finde blubb am Zeielnanfang gefolgt von mehereren Leerzeichen bis zum Dooppelpunkt und nummeriere die Zeilen
for /f "tokens=1,2*delims=: " %%a in ('type "demo.txt"^|findstr /nrc:"^blubb *:"')do (
echo Token1: %%a
echo Token2: %%b
echo Rest : %%c
rem ist der rest "huhu"?
if "%%c"=="huhu" (
set /a "IncrementedLine=%%a-1"
rem Lies nochmal Alles ein und Nummeriere... finde nicht Nichts (Batchlogik für "finde Alles") und finde in "Allem" die Zeielnenummerierug des vorangegangenen find (bitte keienen Suizid begehen XD )
for /f "tokens=1* delims=[]" %%i in ('type "demo.txt"^|find /n /v ""^|find "[!IncrementedLine!]"') do (
echo Zeile: %%i, Inhalt: %%j
set "Var=%%j"
echo ich habe was ich wollte , alles uebrige interessiert nicht mehr ^^!
rem mehr wollen wir nicht auch wenn noch eine passt und brechen die Sache ab (aus der Schleife springen!)
goto :break
)
) else (echo die war es nicht ^^!)
)
:break
echo Ergebnis: %var%
pause
- https://ss64.com/nt/find.html
- https://ss64.com/nt/findstr.html
- https://ss64.com/nt/delayedexpansion.html
- https://ss64.com/nt/type.html
- https://ss64.com/nt/syntax-esc.html
Batch ist nicht nett...
Wenn ich Du nicht gerade auf Masochismus stehst, lauf weg... Wenn ich Dir einen guten Rat geben kann, lerne Powershell . Da brauchst Du Dich nicht mit solche halsbrecherischen Aktionen herumschlagen.
Batch ist eine Sprache der 80er Jahre. mit jedem technischen Fortschritt wurde etwas hinzugefügt und dabei darauf geachtet, das alles übrige blieb wie es war. Viele Administratoren glichen schon immer irgendwelche Unzulänglichkeiten der Sprache aus indem sie Bugs und Ungereimtheiten nutzten. und all diese Tricksereien mussten lauffähig bleiben (über Generationen). Deshalb ist Batch zu einer relativ konzeptlosen "Zumutung" geworden.
Einen Hang zum Sadismus muss der Entwickler mitbringen.
...eher Masochismus😅
Das ist auch der Grund, weshalb Microsoft inzwischen auf Powershell setzt.
[neuer Kommentar, weil der Editor sonst wegen zu vieler Zeichen meckert...]
Vorarbeit
- Ein initialisierter und grundlegend eingerichteter Raspberry Pi (ich empfehle den offiziellen Beginner's Guide auf deutsch von der offiziellen Homepage), der sich im Heimnetzwerk befindet.
- Den xrdp-Dienst installieren, damit eine Remote-Desktopverbindung zum Pi hergestellt werden kann. Ich empfehle folgenden Link, weil dort die Deinstallation des VNC-Dienstes mit berücksichtigt wird. Beachtet, dass die Remote-Dekstopverbindung nicht mit dem Standard-Benutzer auf dem Pi hergestellt werden kann, sondern dass dazu ein weiterer Benutzer hinterlegt werden muss (siehe dazu erste Antwort hier). Damit dieser User auch Adminrechte hat, ist ein
-- sudo usermod -a -G sudo neuerBenutzername-- sudo usermod -a -G adm neuerBenutzername
notwendig. Die Einstellungen für die Remote-Desktopverbindung (.rdp) müssen gespeichert und der Pfad sich gemerkt werden. Den Pfad benötigen wir noch später.
- Wer dann von der Meldung "Authentication required to refresh system repositories" genervt ist, folgt diesen Hinweisen. Das thinclient-Drive kann entsprechend dieser Anleitung ausgekoppelt werden.
- Zusätzlich muss der VPN-Tunnel vom Client zum Router vorbereitet werden, falls sich der Client nicht im Heimnetzwerk befindet. In meinem Fall lief das über die Fritz!Box-Homepage.
Nun sind die wesentlichen Vorbereitungen abgeschlossen, um mit dem eigentlichen Batch anzufangen.
Quellcode
Grundsätzlich ist eine Text-Datei, zum beispiel mit dem windowseigenen Texteditor zu öffnen, der folgende Quellcode hineinzukopieren, die Datei zu speichern und mit der Endung .bat umzubenennen.
:: "@echo off" unterdrueckt die Ausgabe eines Befehls, sodass nur das Ergebnis des Befehls gedruckt wird; das @ betrifft auch den Befehl selbst
@echo off
:: "setlocal enableDelayedExpansion" aendert die Regeln fuer das Lesen (und Speichern) der Variableninhalte
setlocal enableDelayedExpansion
:: initialisiere den Heimmetzwerknamen (SSID), nach dem = muss ein Leerzeichen stehen
set strSSID= FRITZBox 7520 SZ
:: "cls" loescht den Bildschrim
cls
echo Pruefe die Internetverbindung, indem Google angepingt wird...
:: die IPv4-Adresse von www.google.de lautet 8.8.8.8
ping -4 -n 1 www.google.de
:: mit "set" wird eine Variable deklariert. Ihr wird der Fehlerwert des Ping-Befehls zugewiesen: 0 bedeutet, kein Fehler = Internetverbindung; 1 bedeutet, Fehler = keine Internetverbindung
set numInternet=%errorlevel%
:: "echo." fuegt eine Leerzeile ein
echo.
:: gib das Ergebnis aus
if %numInternet% neq 0 (
msg /TIME:5 %username% Keine Internetverbindung. Anwendung wird beendet.
exit /b) else (
echo Internetverbindung besteht. Pruefe, ob eine Verbindung zum Heimnetzwerk besteht...
echo.
)
:: nun wird der Name des WLAN-Netzwerks ausgelesen und geprueft, ob eine Verbindung zum Heimnetzwerk besteht
:: finde n Leerzeichen am Zeilenanfang, gefolgt von dem Wort "Status", gefolgt von n Leerzeichen bis zum Doppelpunkt und nummeriere die Zeilen
for /f "tokens=1,2*delims=: " %%a in ('netsh wlan show all ^| findstr /nrc:"^ *Status *:"') do (
:: wenn diese Zeile gefunden wurde, pruefe, ob der Status auf "Verbunden" gesetzt ist
if "%%c"=="Verbunden" (
:: wenn der Status auf "Verbunden" gesetzt ist, inkrementiere die Zeile, weil in der naechsten Zeile der Netzwerkname (SSID) hinterlegt ist
set /a "IncrementedLine=%%a+1"
:: laufe nochmals alle Zeilen ab, bis die Zeile mit der SSID erreicht ist
for /f "tokens=1* delims=[]" %%i in ('netsh wlan show all ^| find /n /v "" ^| find "[!IncrementedLine!]"') do (
:: zerlege diese Zeile und extrahiere den Netzwerknamen
for /f "tokens=1,2*delims=:" %%k in ("%%j") do (
set "var=%%l" )
:: wenn der SSID extrahiert wurde, brich ab
goto :break
)
)
)
:break
:: wenn der gefundene Neutzwerkname dem des Heimnetzwerks entspricht, starte die bekannte Remote-Desktopverbindung
if !var!==!strSSID! (echo Heimnetzwerk gefunden. Starte die Remote-Desktop-Verbindung...
chdir "C:\Users\Pfad-zur-RDP-Datei"
start raspberrypi
exit /b) else (echo Wir brauchen einen VPN-Tunnel
chdir "C:\Program Files\WireGuard\"
start /wait wireguard.exe /installtunnelservice "C:\Program Files\WireGuard\Data\Configurations\FritzBox.conf.dpapi"
chdir "C:\Users\Pfad-zur-RDP-Datei"
start /wait raspberrypi
start /wait wireguard.exe /uninstalltunnelservice FritzBox)
Vorwort
Nachdem mir gut und kompetent geholfen wurde, möchte ich mein Arbeitsergebnis gern "veröffentlichen" und anderen zur Verfügung stellen, die mit derselben Herausforderung kämpfen. Meine Lösung kann angepasst und für die individuellen Ziele verändert werden. Ein ganz herzlicher Dank gilt Erzesel und daCypher, die mir in diesem aktuellen Post sowie hier geholfen haben.
Falls jemand Verbesserungsvorschläge oder Ergänzungen hat, sind alle gern eingeladen, diese zu äußern.
Motivation
Ich verwende einen Raspberry Pi, auf dem ich mich per Remote-Desktopverbindung von meinem Windows-Laptop einlogge. Mein Ziel war das Schreiben eines Batch-Skripts, welche diese Verbindung automatisch herstellt und dabei die vorherrschende Netzwerksituation berücksichtigt.
Ablauf
Zunächst wird geprüft, ob überhaupt eine Internetverbindung besteht. Dazu wird Google angepingt. Falls dieser Ping erfolglos bleibt, wird eine Information ausgegeben, die sich selbst sowie die Anwendung nach fünf Sekunden schließt.
Falls eine Internetverbindung besteht, wird geprüft, ob sich der Client im Heimnetzwerk befindet, mit dem auch der Raspberry Pi verbunden ist.
Falls sich der Client im Heimnetzwerk befindet, wird eine Remote-Desktopverbindung gestartet und es kann auf/mit dem Pi gearbeitet werden.
Falls sich der Client nicht im Heimnetzwerk befindet, wird ein VPN-Tunnel zum Router (hier eine Fritz!Box) hergestellt und anschließend wird die bekannte Remote-Desktopverbindung aufgebaut. Sobald diese Remote-Desktopverbindung beendet/geschlossen wird, wird auch der VPN-Tunnel geschlossen und die Anwendung beendet.
Vorarbeit
- Ein initialisierter und grundlegend eingerichteter Raspberry Pi (ich empfehle den offiziellen Beginner's Guide auf deutsch von der offiziellen Homepage), der sich im Heimnetzwerk befindet.
- Den xrdp-Dienst installieren, damit eine Remote-Desktopverbindung zum Pi hergestellt werden kann. Ich empfehle folgenden Link, weil dort die Deinstallation des VNC-Dienstes mit berücksichtigt wird. Beachtet, dass die Remote-Dekstopverbindung nicht mit dem Standard-Benutzer auf dem Pi hergestellt werden kann, sondern dass dazu ein weiterer Benutzer hinterlegt werden muss (siehe dazu erste Antwort hier). Damit dieser User auch Adminrechte hat, ist ein
-- sudo usermod -a -G sudo neuerBenutzername-- sudo usermod -a -G adm neuerBenutzername
notwendig.
- Wer dann von der Meldung "Authentication required to refresh system repositories" genervt ist, folgt diesen Hinweisen. Das thinclient-Drive kann entsprechend dieser Anleitung ausgekoppelt werden.
- Zusätzlich muss der VPN-Tunnel vom Client zum Router vorbereitet werden, falls sich der Client nicht im Heimnetzwerk befindet. In meinem Fall lief das über die Fritz!Box-Homepage.
Nun sind die wesentlichen Vorbereitungen abgeschlossen, um mit dem eigentlichen Batch anzufangen.
Quellcode
Grundsätzlich ist eine Text-Datei, zum beispiel mit dem windowseigenen Texteditor zu öffnen, der folgende Quellcode hineinzukopieren, die Datei zu speichern und mit der Endung .bat umzubenennen.
[neuer Kommentar, weil der Editor sonst wegen zu vieler Zeichen meckert...]
Vorwort
Nachdem mir gut und kompetent geholfen wurde, möchte ich mein Arbeitsergebnis gern "veröffentlichen" und anderen zur Verfügung stellen, die mit derselben Herausforderung kämpfen. Meine Lösung kann angepasst und für die individuellen Ziele verändert werden. Ein ganz herzlicher Dank gilt Erzesel und daCypher, die mir in diesem aktuellen Post sowie hier geholfen haben.
Falls jemand Verbesserungsvorschläge oder Ergänzungen hat, sind alle gern eingeladen, diese zu äußern.
Motivation
Ich verwende einen Raspberry Pi, auf dem ich mich per Remote-Desktopverbindung von meinem Windows-Laptop einlogge. Mein Ziel war das Schreiben eines Batch-Skripts, welche diese Verbindung automatisch herstellt und dabei die vorherrschende Netzwerksituation berücksichtigt.
Ablauf
Zunächst wird geprüft, ob überhaupt eine Internetverbindung besteht. Dazu wird Google angepingt. Falls dieser Ping erfolglos bleibt, wird eine Information ausgegeben, die sich selbst sowie die Anwendung nach fünf Sekunden schließt.
Falls eine Internetverbindung besteht, wird geprüft, ob sich der Client im Heimnetzwerk befindet, mit dem auch der Raspberry Pi verbunden ist.
Falls sich der Client im Heimnetzwerk befindet, wird eine Remote-Desktopverbindung gestartet und es kann auf/mit dem Pi gearbeitet werden.
Falls sich der Client nicht im Heimnetzwerk befindet, wird ein VPN-Tunnel zum Router (hier eine Fritz!Box) hergestellt und anschließend wird die bekannte Remote-Desktopverbindung aufgebaut. Sobald diese Remote-Desktopverbindung beendet/geschlossen wird, wird auch der VPN-Tunnel geschlossen und die Anwendung beendet.
Vorarbeit
- Ein initialisierter und grundlegend eingerichteter Raspberry Pi (ich empfehle den offiziellen Beginner's Guide auf deutsch von der offiziellen Homepage), der sich im Heimnetzwerk befindet.
- Den xrdp-Dienst installieren, damit eine Remote-Desktopverbindung zum Pi hergestellt werden kann. Ich empfehle folgenden Link, weil dort die Deinstallation des VNC-Dienstes mit berücksichtigt wird.
Quellcode
Nacharbeit
- Verknüfung erstellen
- Raspberry-Pi-Icon im Netz heraussuchen und hinterlegen
Fazit
Ich bin wirklich erstaunt, wie schlecht eine Batch-Programmierung umzusetzen ist. Einen Hang zum Sadismus muss der Entwickler mitbringen. Auch ist der Quellcode sehr "zickig" und reagiert schon bei kleinen Fehlern wie fehlende/zusätzliche Leerzeichen sensibel.
Uff. Das muss ich sacken lassen. Danke dir. Sobald ich ein Update habe, schreibe ich meine Lösung hier. Brauche aber einen Moment, das zu verarbeiten.
Nacharbeit
Fazit
Ich bin wirklich erstaunt, wie schlecht eine Batch-Programmierung umzusetzen ist. Einen Hang zum Sadismus muss der Entwickler mitbringen. Auch ist der Quellcode sehr "zickig" und reagiert schon bei kleinen Fehlern wie fehlende/zusätzliche Leerzeichen sensibel.
Wer weitere Fragen zu meiner Implementierung und Umsetzung hat, kann sich gern hier melden...
Viele Grüße,
Christian