Wie lese ich mittels Batch-File (CMD) eine einzelne Zeile aus?

1 Antwort

Vom Fragesteller als hilfreich ausgezeichnet

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.

  1. bleibt nur nochmal lesen und neu Nummerieren und mit der dem IncrementWert selektieren
  2. 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

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.

Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren
Craven120 
Fragesteller
 24.03.2023, 08:55

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.

0
Craven120 
Fragesteller
 28.03.2023, 11:41

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

  1. 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.
  2. 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

  1. Verknüfung erstellen
  2. 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.

0
Craven120 
Fragesteller
 28.03.2023, 12:03

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...]

0
Craven120 
Fragesteller
 28.03.2023, 12:12

[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)
0
Craven120 
Fragesteller
 28.03.2023, 12:19

Nacharbeit

  1. Im Fall einer (sinnvollerweise) aktiven Benutzerkontensteuerung, kann entsprechend dieser Anleitung die Ausführung der Batch ohne ständiges Bestätigen ausgeführt werden. Dann liegt auch gleich eine Verknüpfung vor, die man mit einem Raspberry-Pi-Icon aufhübschen kann.
  2. Hintergründe zur WireGuard-Anwendung auf cmd-Ebene können hier gefunden werden.

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

0
Erzesel  28.03.2023, 12:39
@Craven120

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.

0