-heny-
Goto Top

(Sonder-)zeichen aus Variable entfernen

Hallo,

folgende Ausgangssituation ist gegeben:

set /p string=Geben Sie einen String ein: 
echo %string%

Ich möchte nun aus obiger Variable bestimmte Zeichen entfernen (strippen). Dazu gehören auch Sonderzeichen. Bis jetzt habe ich es wie folgt probiert:

set /p string=Geben Sie einen String ein: 
set string=%string:[=%
set string=%string:]=%
set string=%string:(=%
set string=%string:)=%
echo %string%

Das funktioniert soweit auch ohne Probleme. Kommen jetzt aber oben angesprochene Sonderzeichen (Steuerungszeichen) ins Spiel, wird es heikel.
Eine Beispieleingabe sei die Pipe "<". Gebe ich bei der Userabfrage dieses Zeichen ein, so crashed die Batch-Datei.

Logisch gedacht, folgendes probiert:

set /p string=Geben Sie einen String ein: 
set string=%string:<=%
echo %string%

Bei einer Eingabe von "<" wird nun das Zeichen korrekt gestripped, auch innerhalb eines Strings wie "a<b" erhalte ich als Resultat "ab". Probleme tauchen auf, wenn ich nun z.B. "<>" eingebe.

set /p string=Geben Sie einen String ein: 
set string=%string:<=%
set string=%string:>=%
echo %string%

Obiger Code müsste rein logisch gedacht auch funktionieren. Tippe ich nun "<>" ein, so crashed die Batch-Datei schon wieder. Interessanterweise stürzt die Batch-Datei auch bei der Eingabe von "<" ab (obigen Code vorausgesetzt), obwohl ich die Zeichenersetzung nur um das Sonderzeichen ">" ergänzt habe.

Genauso verhält es sich auch mit einigen anderen Sonderzeichen. Wie kann ich das Problem lösen?

Ich möchte aus einem beliebigen String u.a. folgende Zeichen strippen (in beliebiger Reihenfolge & Kombination):

<>&|:?"/\

Gruß,
heny

Content-Key: 85139

Url: https://administrator.de/contentid/85139

Printed on: April 19, 2024 at 09:04 o'clock

Member: bastla
bastla Apr 10, 2008 at 13:12:04 (UTC)
Goto Top
Hallo -heny-!

Versuch's mal so:
set /p "string=Geben Sie einen String ein: "  
set "string=%string:<=%"  
set "string=%string:>=%"  
echo %string%

Grüße
bastla
Member: -heny-
-heny- Apr 10, 2008 at 13:43:18 (UTC)
Goto Top
Hallo,

das funktioniert schon mal etwas besser.

Jetzt habe ich folgenden Code:

@echo off
set /p "string=Geben Sie einen String ein: "  
set "string=%string:<=%"  
set "string=%string:>=%"  
set "string=%string:&=%"  
set "string=%string:|=%"  
set "string=%string:^=%"  
set "string=%string:"=%"  
set "string=%string:?=%"  
set "string=%string::=%"  
set "string=%string:/=%"  
set "string=%string:\=%"  
echo %string%
pause

Problemlos geht jetzt z.B. die Eingabe von "<>", ">" oder "a<>b".

Bei manchen Eingaben ist das Verhalten dennoch noch etwas komisch, ich liste mal ein paar auf:

Eingabe: "<"
Output:
KEINER, Crash

Eingabe: "|"
Output:
Geben Sie einen String ein: |
=
Drücken Sie eine beliebige Taste . . .

Eingabe: "&"
Output:
KEINER, Crash

Output:
Geben Sie einen String ein: ||
=
Drücken Sie eine beliebige Taste . . .

Eingabe: "|&|"
Output:
Geben Sie einen String ein: |&|
=
Drücken Sie eine beliebige Taste . . .

Eingabe: "^^"
Output:
Geben Sie einen String ein: ^^
"=  
Drücken Sie eine beliebige Taste . . .

Komplexere Eingaben hingegen funktionieren meist ohne Probleme. Problematisch scheint hauptsächlich die alleinige Nutzung von Sonderzeichen zu sein, ohne andere Zeichen (z.B. numerische).

Hier ein Beispiel, das problemlos funktioniert:

Output:
Geben Sie einen String ein: <>Dies&ist|ein||&Test"""  
DiesisteinTest
Drücken Sie eine beliebige Taste . . .

Ich bin ziemlich verwirrt. :/

Gruß,
heny
Member: bastla
bastla Apr 10, 2008 at 13:57:25 (UTC)
Goto Top
Hallo -heny-!

Da offensichtlich die (eingegebenen) Anführungszeichen stören, diese zuerst eliminieren:
@echo off
set /p "string=Geben Sie einen String ein: "  
if defined string set "string=%string:"=%"  
if defined string set "string=%string:<=%"  
if defined string set "string=%string:>=%"  
if defined string set "string=%string:&=%"  
if defined string set "string=%string:|=%"  
if defined string set "string=%string:^=%"  
if defined string set "string=%string:?=%"  
if defined string set "string=%string::=%"  
if defined string set "string=%string:/=%"  
if defined string set "string=%string:\=%"  
if defined string (echo %string%) else (echo Keine verwertbare Eingabe!)
pause

Problematisch scheint hauptsächlich die alleinige Nutzung von Sonderzeichen zu sein
Wenn der String zwischendurch schon mal leer ist, nicht weiter daran herumdoktern face-wink ...

Grüße
bastla
Member: -heny-
-heny- Apr 10, 2008 at 14:01:56 (UTC)
Goto Top
Hallo,

die Versetzung der "-Eliminierung an die oberste Stelle behebt das Problem nicht. Wenn ich nur Anführungsstriche eingebe, stürzt das Batch-File wieder ab.

Wenn der String zwischendurch schon mal leer
ist, nicht weiter daran herumdoktern face-wink ...

Was genau meinst du damit? Daraus werde ich nicht ganz schlau.

Gruß,
heny
Member: bastla
bastla Apr 10, 2008 at 14:39:07 (UTC)
Goto Top
Hallo -heny-!

Was genau meinst du damit?
Da es nicht sinnvoll sein kann, in einem eigentlich nicht mehr existenten String (da ursprünglich nur aus Sonderzeichen bestehend und früher oder später von all diesen bereits befreit) noch weitere Ersetzungen zu versuchen, sorgt "if defined string" dafür, dass nur, wenn noch Zeichen vorhanden sind, weiterhin ersetzt wird.

Wenn ich nur Anführungsstriche eingebe, stürzt das Batch-File wieder ab.
Wie machst Du das? Mit meiner vorhin geposteten Version (wieder heruntergeladen und als "str.cmd" gespeichert) sieht das Ergebnis bei mir so aus:
D:\>str
Geben Sie einen String ein: ""  
Keine verwertbare Eingabe!
Drücken Sie eine beliebige Taste . . .

Grüße
bastla
Member: -heny-
-heny- Apr 10, 2008 at 14:51:34 (UTC)
Goto Top
Hallo,

ups, sorry. Da habe ich dein Script nicht genau angeschaut. Wobei ich darauf, dass man eine nicht vorhandene Variable nicht weiter bearbeiten kann, auch hätte selber kommen können. ;)
Naja, hinterher ist man immer schlauer.

Das funktioniert soweit top, nur fehlen anscheinend noch ein paar Zeichen, die Probleme verursachen können. Unter anderem musste ich noch ")" herausstrippen, da das Batch-File sonst ebenfalls crashed.

Im folgenden der bisherige Code:

@echo off
:start
set /p "string=Geben Sie einen String ein: "  
if defined string set "string=%string:"=%"  
if defined string set "string=%string:<=%"  
if defined string set "string=%string:>=%"  
if defined string set "string=%string:&=%"  
if defined string set "string=%string:|=%"  
if defined string set "string=%string:^=%"  
if defined string set "string=%string:?=%"  
if defined string set "string=%string::=%"  
if defined string set "string=%string:/=%"  
if defined string set "string=%string:\=%"  
if defined string set "string=%string:)=%"  
if defined string (echo %string%) else (echo Keine verwertbare 

Eingabe!)
goto :start

Fallen dir noch weitere problematische Sonderzeichen ein?
Und was genau bewirken die Anführungsstriche vor und nach dem string=%string^=%?

Gruß,
heny
Member: bastla
bastla Apr 10, 2008 at 15:06:39 (UTC)
Goto Top
Hallo -heny-!

Da habe ich dein Script nicht genau angeschaut.
Passiert mir öfter, dass ich mein Script nicht genau (genug) anschaue ... face-wink

Fallen dir noch weitere problematische Sonderzeichen ein?
Auf Anhieb nicht (wobei sich die Frage stellt, in welchem Zusammenhang die Probleme entstehen könnten).

Und was genau bewirken die Anführungsstriche vor und nach dem string=%string^=%?
Ist ein Biber-Special: Damit kannst Du einerseits zB auch Leerzeichen in eine Variable schreiben, andererseits weist Du damit im Prinzip den Interpreter an, (bis auf die Variablenzuweisung) den Teil dazwischen eben nicht zu interpretieren, sondern einfach als Text zu behandeln.

Da ich mich an keine Situation erinnern kann, in der diese Schreibweise nachteilig gewesen wäre, verwende ich sie mittlerweile eigentlich standardmäßig (auch wenn es keinen besonderen Anlass dafür gibt).
In der ersten Batchzeile solltest Du noch ein "& setlocal" ergänzen, damit die nachfolgend erstellte(n) Variable(n) nur für den aktuellen Batch gelten und nachher keine Reste mehr davon herumliegen.

Grüße
bastla
Member: -heny-
-heny- Apr 10, 2008 at 15:11:48 (UTC)
Goto Top
Hallo,

Reicht da folgendes, was ich eh schon im Script stehen habe?

(...)
    if NOT "%cmdextversion%"=="2" goto wrongcmdext  
    setlocal EnableDelayedExpansion
(...)

Gruß,
heny
Member: bastla
bastla Apr 10, 2008 at 15:18:12 (UTC)
Goto Top
Hallo -heny-!

Reicht; "DelayedExpansion" verwende ich übrigens nur, wenn's gar nicht anders geht (wird aber vermutlich bei Deinem Batch der Fall sein).

Grüße
bastla
Member: -heny-
-heny- Apr 10, 2008 at 15:40:16 (UTC)
Goto Top
Hallo,

ok. Noch eine andere kleine Problematik:

ich habe einen Aufruf irgendwo im Script

call :stripcharacters VariablenName

Die Funktion :stripcharacters entfernt alle Sonderzeichen aus einem String, der in einer Variable gespeichert ist.

Der Inhalt der Funktion ist wie folgt:

    :stripcharacters
    if defined %* set "%*=%%*%:"=%"  
    if defined %* set "%*=%%*%:<=%"  
    if defined %* set "%*=%%*%:>=%"  
    if defined %* set "%*=%%*%:&=%"  
    if defined %* set "%*=%%*%:|=%"  
    if defined %* set "%*=%%*%:^=%"  
    if defined %* set "%*=%%*%:?=%"  
    if defined %* set "%*=%%*%:=%"  
    if defined %* set "%*=%%*%:/=%"  
    if defined %* set "%*=%%*%:\=%"  
    if defined %* set "%*=%%*%:)=%"  
    goto :eof

Die Funktion soll den durch den "call"-Befehl übergebenen Variablennamen (ohne %%) nutzen und entsprechend die Sonderzeichen aus der Variable strippen. Es hängt allerdings an einer Stelle im "set"-Befehl. Es werden keine Sonderzeichen aus der Variable entfernt.

Baue ich ein "echo" ein, um zu sehen woran es hängt

echo if defined %* set "%*=%%*%:"=%"  

erhalte ich folgenden "echo"-Output:

if defined VariablenName set "VariablenName=%*:"="  

Korrekt müsste der Output wie folgt lauten:

if defined VariablenName set "VariablenName=%VariablenName:"=%"  

Wie kann ich bewerkstelligen, das der übergebene Parameter (der Variablenname) auch korrekt eingesetzt wird, damit die Sonderzeichen-Entfernung problemlos funktioniert?

Gruß,
heny
Member: bastla
bastla Apr 10, 2008 at 16:48:07 (UTC)
Goto Top
Hallo -heny-!

Du könntest als Workaround den Variableninhalt anfangs in die Variable "string" schreiben, den obigen Code als Unterprogramm verwenden, und dann erst die Zuweisung an die benötigte Variable vornehmen.

Vorweg stellt sich allerdings die Frage, woher eigentlich derartig verquere Strings überhaupt kommen sollen - den Fall "direkte Benutzereingabe" hast Du schon abgedeckt, und für das Auslesen aus einer Datei (oder die Verarbeitung der Ausgabe eines Programmes) sollte es auch mit der beschriebenen Methode klappen.

Als Beispiel eine Datei "Test.txt" mit folgendem Inhalt:
(Hoffentlich) kein '#+*~ ^Problem.  
"<>Dies&ist|ein||&Test""""  
Noch einige besondere §$%&/()=? Zeichen
Der Batch dazu:
@echo off & setlocal enabledelayedexpansion
set /a Nr=1
for /f "delims=" %%i in (Test.txt) do set "string=%%i" & call :ProcessLine  
echo\
echo Nach der Schleife vorhandene Variable:
set Test
goto :eof

:ProcessLine
call :StripCharacters
set "Test%Nr%=%string%"  
echo !Test%Nr%!
set /a Nr+=1
goto :eof

:StripCharacters
if defined string set "string=%string:"=%"  
if defined string set "string=%string:<=%"  
if defined string set "string=%string:>=%"  
if defined string set "string=%string:&=%"  
if defined string set "string=%string:|=%"  
if defined string set "string=%string:^=%"  
if defined string set "string=%string:?=%"  
if defined string set "string=%string::=%"  
if defined string set "string=%string:/=%"  
if defined string set "string=%string:\=%"  
if defined string set "string=%string:(=%"  
if defined string set "string=%string:)=%"  
goto :eof

Natürlich ist dieser Lösungsweg nicht so elegant wie Deine "Function", aber mir fällt momentan kein Weg ein, wie sowohl die nötigen Anführungszeichen (außen herum) gesetzt werden können, als auch die Auflösung der Variablen innerhalb dieser Anführungszeichen (nach dem "=") erfolgen soll - vielleicht hat ja Biber noch eine Idee dazu ...

Grüße
bastla
Member: -heny-
-heny- Apr 10, 2008 at 19:28:47 (UTC)
Goto Top
Hallo,

hm, ich glaube wir haben da aneinander vorbei geredet. Die Variable, welche beim Aufruf durch "call" übergeben wird hat ihren Inhalt aus einer Benutzereingabe. Ich möchte die gesamten "if defined ..." Befehle in der Batch-Datei jeweils durch den Aufruf der Prozedur ersetzen, da ich mir dann etliche Zeilen unnötigen Code spare.

Gruß,
heny
Member: bastla
bastla Apr 10, 2008 at 19:49:49 (UTC)
Goto Top
Hallo -heny-!

Fällt Dir auf, dass ich ebenfalls ein Unterprogramm verwendet habe (und dieses daher auch so oft wie nötig aufrufen kann)?

Der Unterschied besteht eigentlich nur darin, dass vor dem Aufruf der zu bereinigende Text in die Variable "string" zu schreiben ist und sich auch danach noch dort befindet - daher die Eingabe gleich in "string" speichern (wie oben schon durchgespielt) und erst nach dem Unterprogrammaufruf das Ergebnis der gewünschten Variablen zuweisen, also etwa:

@echo off & setlocal
set /p "string=Geben Sie einen String ein: "  
call :StripCharacters
set "Eingabe=%string%"  
...
...

Grüße
bastla
Member: -heny-
-heny- Apr 11, 2008 at 16:04:44 (UTC)
Goto Top
Hallo,

ich habe das ganze entsprechend deiner Hilfe jetzt wie folgt gelöst:

     call :stripcharacters enemyname
     if "%flagblank%"=="1" goto mainmenu  
     if "%flagspecialchar%"=="1" goto mainmenu  

    :stripcharacters
    if NOT "!%*!"=="" (  
        set flagblank=0
        set flagspecialchar=0
        set stripstring=!%*!
        if defined stripstring set "stripstring=!stripstring:"=!"  
        if defined stripstring set "stripstring=!stripstring:<=!"  
        if defined stripstring set "stripstring=!stripstring:>=!"  
        if defined stripstring set "stripstring=!stripstring:&=!"  
        if defined stripstring set "stripstring=!stripstring:|=!"  
        if defined stripstring set "stripstring=!stripstring:^=!"  
        if defined stripstring set "stripstring=!stripstring:?=!"  
        if defined stripstring set "stripstring=!stripstring:/=!"  
        if defined stripstring set "stripstring=!stripstring:(=!"  
        if defined stripstring set "stripstring=!stripstring:)=!"  
        if defined stripstring (
            set %*=!stripstring!
        ) else (
            set flagspecialchar=1
            echo.
            echo !%lang%specialcharinput!
            echo.
            if "%sbreaks%"=="1" pause  
        )
    ) else (
        set flagblank=1
        echo.
        echo !%lang%blankinput!
        echo.
        if "%sbreaks%"=="1" pause  
    )
    goto :eof

Da steckt noch einiges an Code drin, der ohne den Rest des Batch-Files unverständlich ist, aber zumindest funktioniert es jetzt so wie ich möchte. Vielleicht hilft das ja irgendjemandem, deswegen habe ich den Code noch mal geposted.

Danke noch mal!

Gruß,
heny