Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit

Unverständlicher Tokenizer in Klammern

Frage Entwicklung Batch & Shell

Mitglied: jeb-the-batcher

jeb-the-batcher (Level 1) - Jetzt verbinden

18.09.2010 um 22:17 Uhr, 2849 Aufrufe, 12 Kommentare

Bei dem Versuch den Batch-Tokenizer (der eine Zeile in einzelne Teile zerlegt), dachte ich einem guten Modell zur Erklärung schon recht nah zu sein.
Aber dann habe ich, ein mir vollkommen unerklärliches Phänomen entdeckt.

Das es Probleme mit Labeln in Klammern gibt ist ja schon länger bekannt.
Bisher war ich der Meinung, das Label nur als letztes in einem Klammerblock verboten sind

01.
@echo off 
02.
03.
:MeinLabel 
04.
echo Klappt 
05.
06.
 
07.
08.
echo Klappt nicht 
09.
:MeinLabel 
10.
)
aber dann bin ich auf einen Beitrag gestoßen, bei dem auch innerhalb eines Blocks ein Problem entsteht.

01.
@echo off 
02.
03.
echo start 
04.
:comment 
05.
:comment 
06.
echo KLAPPT 
07.
08.
 
09.
10.
echo start 
11.
::comment 
12.
:comment 
13.
echo KLAPPT 
14.
15.
 
16.
17.
echo start 
18.
:comment 
19.
::comment 
20.
echo KLAPPT nicht 
21.
)
Dann habe ich noch ein wenig gespielt, und bin auf ein noch ungewöhlicheres Verhalten gestoßen
01.
@echo off 
02.
03.
:label eins zwei drei ^ 
04.
 
05.
WegIsses echo two three 
06.
echo Nur das erste Token ist weg 
07.
08.
echo --- 
09.
10.
:label eins zwei drei^ 
11.
 
12.
WegIsses echo two three 
13.
echo Jetzt ist es ganz weg 
14.
15.
 
16.
:label eins zwei drei ^ 
17.
 
18.
WegIsses echo two three 
19.
echo Ohne Klammer ist es immer weg
Ausgabe
two three
Nur das erste Token ist weg
---
Jetzt ist es ganz weg
---
Ohne Klammer ist es immer weg

Ohne Klammern ist das Verhalten normal, das Caret am Ende wird als Multiline ausgewertet, die nächste Zeile wird gelesen, da die aber leer ist wird das <LF> der leeren Zeile Escaped, damit ist kein Zeilenende mehr da und die nächste Zeile wird auch noch an das Multiline dran gehängt.

Varianten davon
01.
@echo off 
02.
setlocal EnableDelayedExpansion 
03.
echo Hallo ^ 
04.
 
05.
Dies zeigt einen Text mit Zeilenumbruch 
06.
echo  ----- 
07.
set lf=^ 
08.
 
09.
 
10.
rem Zwei Leerzeilen sind wichtig, damit wird jetzt ein einzelnes LF erzeugt 
11.
rem Allerdings kann man ein LF nur mit DelayedExpansion ausgeben 
12.
echo Erste Zeile!LF!Zweite Zeile
Ausgabe
Hallo
Dies zeigt einen Text mit Zeilenumbruch
Erste Zeile
Zweite Zeile

Aber wie kann man das verschwinden eines einzelnen Token in der Klammer erklären ?

jeb
Mitglied: rubberman
19.09.2010 um 16:51 Uhr
Hallo jeb,

unverständlich ist und bleibt das für mich auch.
Vielleicht liegt des Rätsels Lösung in der Art und Weise wie mit Zeilenumbrüchen in Multilines umgegangen wird.
01.
@echo off &setlocal &prompt ¯¯¯ &echo on 
02.
 
03.
04.
echo Test 
05.
06.
 
07.
08.
echo Hallo 
09.
echo Test 
10.
)
Ausgabe:
01.
»»» (echo Test ) 
02.
Test 
03.
 
04.
»»» ( 
05.
echo Hallo 
06.
 echo Test 
07.
08.
Hallo 
09.
Test
Die Frage ist, woher kommen die Leerzeichen (hinter "Test" im ersten Beispiel bzw. vor dem zweiten echo im zweiten Beispiel). Werden Zeilenumbrüche tatsächlich als Leerzeichen interpretiert bzw. wird ein zusätliches Leerzeichen angehängt? Kann eigentlich nicht sein, denn die Erzeugung des Line Feed Characters würde auch im Multiline Block funktionieren.
01.
@echo off &setlocal enabledelayedexpansion &prompt ¯¯¯ &echo on 
02.
 
03.
04.
set LF=^ 
05.
 
06.
 
07.
 
08.
09.
echo a!LF!b
Ausgabe:
01.
»»» (set LF= 
02.
03.
 
04.
»»» echo a!LF!b 
05.
06.
b
Andererseits deutet einiges auf die Ersetzung des Zeilenumbruches hin. Ein Caret escapet ja normalerweise nur ein Zeichen. Der "normale" Zeilenumbruch besteht aber aus CR+LF. Zwei Zeichen, hmm...
Und wenn man sich die Erzeugung des LF Characters ansieht, käme ja noch ein zusätzliches CR dazu, das es zu escapen gilt.

Noch habe ich da auch keine Idee, wie man nachvollziehbar testen kann.

Grüße
rubberman
Bitte warten ..
Mitglied: miniversum
19.09.2010 um 18:27 Uhr
Hat jetzt nicht wirklich mit diesem Thema zu tun sondern vielleicht eher ein allgemeinerer Kommentar:
Ich würde solche "fragwürdigen" Konstrukte wie Excape Zeichen am ende der Zeile und dergleichen einfach nicht benutzen. Da mach ich mit bei einer batch Datei lieber etwas ausführlicher und mehr Arbeit und dafür vermeide ich so Sachen ...
Bitte warten ..
Mitglied: rubberman
19.09.2010 um 18:56 Uhr
Hallo miniversum.

Ich gebe dir ja Recht. Man muss es nicht nutzen, es gibt bessere Möglichkeiten. Aber das ist auch nicht der Sinn der Übung.
Es geht nur darum herauszufinden, wie cmd.exe solchen Code verarbeitet, um möglichst allgemeingültige Regeln davon abzuleiten. Das wiederum hilft, wenn irgendein Batchfile nicht so funktioniert, wie man es erwartet. Ggf. findet man dann den Grund und bestenfalls auch eine Lösung ...
Ich persönlich finde es sehr gut, dass sich mal jemand mit dieser "Grundlagenforschung" beschäftigt. Das Internet hat da so gut wie nichts parat.

Grüße
rubberman
Bitte warten ..
Mitglied: jeb-the-batcher
19.09.2010 um 19:12 Uhr
Zitat von miniversum:
Ich würde solche "fragwürdigen" Konstrukte wie Excape Zeichen am ende der Zeile und dergleichen einfach nicht
benutzen. Da mach ich mit bei einer batch Datei lieber etwas ausführlicher und mehr Arbeit und dafür vermeide ich so
Sachen ...

Wenn man wissen möchte wie und warum etwas funktioniert, muss man sich eben Tests ausdenken die etwas über die inneren Strukturen verraten.
Ohne sowas würden wir noch in Höheln wohnen und die Erde für eine Scheibe halten(und den Batch Interpreter für einen Zufallsgenerator)

Zitat von rubberman:
Andererseits deutet einiges auf die Ersetzung des Zeilenumbruches hin. Ein Caret escapet ja normalerweise nur ein Zeichen. Der
"normale" Zeilenumbruch besteht aber aus CR+LF. Zwei Zeichen, hmm...
Und wenn man sich die Erzeugung des LF Characters ansieht, käme ja noch ein zusätzliches CR dazu, das es zu escapen
gilt.


Das mit dem "verschwundenen" <CR> ergibt sich aus Phase1.1

Nach dem ersetzen der Prozent Phase, werden alle <CR> entfernt (Daher können die ja auch nur mit !CR! ausgegeben werden).
Daher klappt der LF Trick.

Als Test für das <CR> verschwinden
01.
@echo off 
02.
cls 
03.
setlocal EnableDelayedExpansion 
04.
call :CreateCR 
05.
set "empty=" 
06.
echo Eine %CR%Zeile1 
07.
echo Eine ^%CR%Zeile2 
08.
echo Eine ^%CR%&Zeile3 
09.
echo Leer ^%empty%& geht auch 
10.
echo Eine Laus oder doch !CR!eINE mAUS 
11.
goto :eof 
12.
 
13.
::: Erzeugt ein einzelnes CR Zeichen in einer Variable 
14.
:CreateCR  
15.
setlocal EnableDelayedExpansion EnableExtensions  
16.
set "X=."  
17.
for /L %%c in (1,1,13) DO set "X=!X:~0,4093!!X:~0,4093!" 
18.
REM In X werden 8186 Punkte abgelegt, man kann aber auch was anderes nehmen 
19.
 
20.
REM Jetzt muss genau die richtige Länge ausgegeben werden 
21.
REM Dann passt beim expandieren der Zeile und der anschliessenden Ausgabe das <CR><LF> nicht mehr in den Puffer 
22.
REM sondern nur noch das <CR> 
23.
echo !X!123 > %temp%\cr.tmp 
24.
 
25.
REM Damit hinterher aber die Zeile komplett gelesen werden kann, noch direkt ein Extra <CR><LF> anhängen 
26.
echo\>> %temp%\cr.tmp  
27.
 
28.
REM Jetzt noch die Datei einlesen, im ersten Token sind dann die Punkte im Zweiten das goldene <CR> 
29.
for /f "tokens=2 usebackq" %%a in ("%temp%\cr.tmp") do (  
30.
	endlocal  
31.
	set "cr=%%a" 
32.
	goto :eof  
33.
)  
34.
REM Am Schluss noch ein goto :eof, falls es Probleme mit der Datei gab 
35.
goto :eof
Ausgabe
Eine Zeile1
Eine Zeile2
Eine &Zeile3
Leer & geht auch
eINE mAUS oder doch

Bei der letzten Zeile ist natürlich der gesamte Satz ausgegeben worden, aber durch das CR ist der Cursor halt wieder zum Zeilenanfang gesprungen.

jeb
Bitte warten ..
Mitglied: miniversum
19.09.2010 um 19:23 Uhr
Zitat von jeb-the-batcher:
Wenn man wissen möchte wie und warum etwas funktioniert, muss man sich eben Tests ausdenken die etwas über die inneren
Strukturen verraten.
Ohne sowas würden wir noch in Höheln wohnen und die Erde für eine Scheibe halten(und den Batch Interpreter für
einen Zufallsgenerator)
1. Testest du das mit allen Windowsversionen und alles Servicepacks? Kannst du sicherstellen das sich nicht ab einem gewissen Versionsstand das Verhalten anders ist?
2. Würdest du nach deiner "Untersuchung" solche Konstrukte wirklich ruhigen Gewissens verwenden?
3. Was nützt dir diese "Untersuchung" undokumentierter Funktionen für die du keine Garantie hast das es nicht doch noch Ausnahmefälle geben wird die ein anderes Verhalten hervorrufen?
4. Praktischer nutzen?
Bitte warten ..
Mitglied: rubberman
19.09.2010 um 19:43 Uhr
Zitat von jeb-the-batcher:
Das mit dem "verschwundenen" <CR> ergibt sich aus Phase1.1
Stimmt.
Was ist aber mit den (zumindest angezeigten) zusätzlichen Leerzeichen? Irgendetwas muss im Multiline Block anders laufen als sonst.

Grüße
rubberman
Bitte warten ..
Mitglied: jeb-the-batcher
19.09.2010 um 20:19 Uhr
1. Ich teste mit den Versionen die ich habe, und ich gehe davon aus, dass auch bei Microsoft niemand etwas ohne guten Grund ändert.
2. Es geht mir nicht um die Konstrukte, mir geht es darum zu erklären warum man z.B. für verschiedene Sonderzeichen unterschiedliche Wege gehen muss um sie auszugeben.
01.
echo Zeig mir ein Prozent %% 
02.
echo Zeig mir ein Ampersand ^& 
03.
echo Zeig mir ein Ausrufezeichen ^^! 
Ohne Untersuchung, ist das bloß rumgerate.

3. Wie bei 2., es geht nicht um die undokumentierten Funktionen an sich, aber wenn ich den Parser verstehe, dann weiß ich auch was machbar ist und was eben nicht.
Du hast natürlich recht, bei den Grenzfällen kann man nicht davon ausgehen, dass die immer in allen Versionen funktionieren, weil das möglicherweise nicht gewollte sondern nur Nebeneffekte der Programmierung sind.
z.B. verhält sich
01.
set "caret=^" 
02.
call echo und jetzt ein Vista Crash %%caret%% 
03.
rem für Vista hilft nur ein Kill, XP dagegen ignoriert das Multiline beim zweiten Expandieren.
Es läßt sich naturbedingt hier nicht feststellen, ob es noch unentdecktes Verhalten gibt, dazu müßte man wirklich alles testen (und soviel Zeit habe ich grade nicht).

4. Wie in 2. und 3. beschrieben, Wissen über die genaue Syntax.
Und Forschung hat selten einen direkten praktischen Nutzen, sollte man es dann lieber direkt lassen?

Ich bin professioneller Ansi-C Programmierer, und kann mich noch an meine Anfangszeit erinnern, bei der ich Dinge übernommen habe ohne zu verstehen, warum die da so stehen, heute weiß ich bei jedem Ausdruck was der Compiler oder der Linker dazu denkt und daraus erzeugt.
Und wenn was nicht läuft kann ich herrausfinden ob mein Code einen Fehler hat oder der Compiler, früher konnte ich nur im Nebel stochern.
Bitte warten ..
Mitglied: miniversum
19.09.2010 um 22:29 Uhr
Nur so ein Beispiel warum ich das Problematisch sehe. Dein Code:
01.
echo Zeig mir ein Prozent %% 
02.
echo Zeig mir ein Ampersand ^& 
03.
echo Zeig mir ein Ausrufezeichen ^^! 
ergibt bei mir (Windows xp pro mit sp3 und den aktuellen Updates) :
01.
Zeig mir ein Prozent % 
02.
Zeig mir ein Ampersand & 
03.
Zeig mir ein Ausrufezeichen ^!
und
01.
echo Zeig mir ein Ausrufezeichen ^! 
ergibt:
01.
Zeig mir ein Ausrufezeichen !
Also hast du hier anscheinend schon Unterschiede, nur mal als ein Beispiel.
Der Vergleich mit ANSI-C ist auch interessant weil ich selbst aus Erfahrung weiß das verschiedene (mehr oder weniger gute, aber angeblich immer ANSI konforme Compiler) den identischen C Code in unterschiedlichen Maschinencode umsetzen können, wenn es z.B. um Strukturen geht.
Das Argument
1. Ich teste mit den Versionen die ich habe, und ich gehe davon aus, dass auch bei Microsoft niemand etwas ohne guten Grund ändert.
schließt ja nicht aus, dass mit einem bestimmtem Update dennoch eine Änderung dazu kommt, der Programmierer auch den Grund kennt, Du aber nicht.
Und da Fehler und unerwartetes Verhalten in Batch Skripten erwiesenermaßen abhängig von der Version und der eingestellten Sprache ist (ja das ist bei einigen Befehlen wirklich so) und ich auch schon Unterschiede in Abhängigkeit vom Speicherort der Batch Datei (Lokal oder Netzwerkpfad) erlebt habe bevorzuge ich es eben solche "grenzwertigen" Konstrukte nicht zu benutzen und im Fehlerfall lieber das echo off bzw. an der betreffenden Stelle ein echo on einzufügen um zu sehen was wirklich geschieht.
Bitte warten ..
Mitglied: jeb-the-batcher
20.09.2010 um 12:59 Uhr
Zitat von miniversum:
Nur so ein Beispiel warum ich das Problematisch sehe. Dein Code:
...
ergibt:
01.
Zeig mir ein Ausrufezeichen ! 
02.
> 
Also hast du hier anscheinend schon Unterschiede, nur mal als ein Beispiel.

Beim Ausrufenzeichen gibt es keinen Unterschied, ich habe nur vergessen das
01.
setlocal EnableDelayedExpansion

mit anzugeben.

Und spätestens an der Stelle ist es dann doch recht hilfreich, wenn man versteht, warum man bei Ausrufezeichen zwei Carets benötigt, bei allen anderen aber nur eins, und warum man ein Prozent gar nicht mit Carets escapen kann.



Der Vergleich mit ANSI-C ist auch interessant weil ich selbst aus Erfahrung weiß das verschiedene (mehr oder weniger gute,
aber angeblich immer ANSI konforme Compiler) den identischen C Code in unterschiedlichen Maschinencode umsetzen können, wenn
es z.B. um Strukturen geht.
Aber das ist ja auch kein Problem und durchaus erlaubt, wenn man die ISO/IEC-Norm gelesen hat, weiß man an welchen Stellen ein Ansi-C Compiler Freiheiten hat, und wodrauf man sich absolut verlassen kann (Sonst ist er halt nicht mehr ISO-konform).
Bitte warten ..
Mitglied: jeb-the-batcher
21.09.2010 um 18:47 Uhr
Ich hab ein wenig geforscht...

Und ich denke ich kann es jetzt halbwegs beschreiben.

In einem Klammerblock wirken sich label direkt auf die nächste Zeile aus.
Der erste Token der nächsten Zeile wird als Kommando betrachtet, was ja im allgemeinen ohnehin so ist.
Allerdings in diesem Fall ohne Ausnahme, sprich auch ein Label oder eine schliessende Klammer wird nur noch als Kommando gesehen.


Sprich, hier wird versucht ::label2 (beachte die zwei Doppelüunkte) auszuführen, was fehlschlägt
01.
02.
:label1 
03.
::label2 
04.
)
Dies schlägt komplett fehl weil keine schliessende Klammer gefunden wird(die wird als Kommando angesehen)
01.
02.
echo 1 
03.
:label1 
04.
)
Das klappt allerdings
01.
02.
echo 1 
03.
:label1 
04.
echo nix)
Und alle "geraden" Lableblöcke funktionieren
01.
02.
echo 1 
03.
:label1a 
04.
:label1b 
05.
echo2 
06.
:label2a 
07.
:label2b 
08.
)
Der spannende Teil ist, wie die zweite Zeile interpretiert wird
01.
02.
echo 1 
03.
:label der eine Sonderbehandlung der naechsten Zeile erzeugt 
04.
:\..\%~nx0&echo Und dadruch sehen wir dies 
05.
)
jeb - immer auf der Suche
Bitte warten ..
Mitglied: rubberman
21.09.2010 um 23:36 Uhr
Erstaunlich ^^
Ähnliches hatte ich auch getestet, war aber mit dem Leerzeichen als vermeintlichen Übeltäter auf der falschen Fährte.

Der letzte Code endete bei mir erst mal in einem Fehler (Leerzeichen im Name ).
01.
02.
echo 1 
03.
:label der eine Sonderbehandlung der naechsten Zeile erzeugt 
04.
:\..\%~snx0&echo Und dadruch sehen wir dies 
05.
)
... schaffte Abhilfe.

Grüße
rubberman
Bitte warten ..
Mitglied: jeb-the-batcher
21.09.2010 um 23:56 Uhr
Der Effekt ist ja auch an sich erstaunlich,

es wird nach der Datei gesucht, aber gestartet wird sie nicht!

Einfacher ist es daher
01.
02.
:lab2 
03.
:&echo Einfache Ausgabe 
04.
 
05.
:lab3 
06.
:: 2>nul  
07.
)
Aber ganz zufrieden bin ich nicht.

01.
(  
02.
:label eins zwei drei ^  
03.
 
04.
WegIsses echo two three  
05.
echo Nur das erste Token ist weg  
06.
)  
07.
echo ---  
08.
(  
09.
:label eins zwei drei^  
10.
 
11.
WegIsses echo two three  
12.
echo Jetzt ist es ganz weg  
13.
) 
Denn diesen Teil kann ich mir damit immer noch nicht richtig erklären

Bei deinen Leerzeichen könnte es sich um versuchte Formatierung handeln (gewollt aber nicht so richtig gekonnt), oder eben doch um einen Hinweis, wie Klammern ausgewertet werden.

jeb
Bitte warten ..
Neuester Wissensbeitrag
Festplatten, SSD, Raid

12TB written pro SSD in 2 Jahren mit RAID5 auf Hyper-VServer

Erfahrungsbericht von Lochkartenstanzer zum Thema Festplatten, SSD, Raid ...

Ähnliche Inhalte
Batch & Shell
gelöst Mit Powershell Daten löschen, die eckige Klammern im Namen haben (2)

Frage von arduino zum Thema Batch & Shell ...

Heiß diskutierte Inhalte
Windows Userverwaltung
Ausgeschiedene Mitarbeiter im Unternehmen - was tun mit den AD Konten? (34)

Frage von patz223 zum Thema Windows Userverwaltung ...

LAN, WAN, Wireless
gelöst Server erkennt Client nicht wenn er ausserhalb des DHCP Pools liegt (28)

Frage von Mar-west zum Thema LAN, WAN, Wireless ...

LAN, WAN, Wireless
FritzBox, zwei Server, verschiedene Netze (21)

Frage von DavidGl zum Thema LAN, WAN, Wireless ...

Viren und Trojaner
Aufgepasst: Neue Ransomware Goldeneye verbreitet sich rasant (20)

Link von Penny.Cilin zum Thema Viren und Trojaner ...