Czy pliki wsadowe DOS stanowią pełnoprawny język programowania? Są istotne przyczyny, by twierdzić że nie. O ile da się stworzyć wiele użytecznych skryptów związanych z zarządzaniem plikami na dyskach, bo do tego właśnie programy wsadowe służą, o tyle jeśli mówimy o pisaniu plików wsadowych dla DOS-a jako takiego (a nie dla Windows) to będzie nam brakowało między innymi jakichkolwiek działań arytmetycznych czy podprogramów, a więc dosyć podstawowych funkcjonalności w językach ogólnego przeznaczenia. Ale okazuje się, że wciąż istnieje (w miarę) sensowny sposób na wykonywanie obliczeń w programach wsadowych, i nie mówię tutaj ani o rozszerzeniach wprowadzonych w Windows (SET /A
, porównania liczb w poleceniu IF
) ani o poleganiu na zewnętrznych programach wykonujących takie działanie do zastoswania w programach wsadowych (bo takie były, np. XSET
, EVAL
). Na końcu zaprezentuję działający program wsadowy obliczający NWD dwóch liczb za pomocą algorytmu Euklidesa.
Najpierw przypomnę, jakie w ogóle działania można wykonywać na zmiennych za pomocą poleceń DOS-u (dostępnych także w wierszu poleceń Windows). Mowa oczywiście o zmiennych środowiskowych, które są wykorzystywane jako zwykłe zmienne w obrębie plików wsadowych dla Windows i DOS. Po pierwsze, można przypisać zmiennej określoną, tekstową wartość, np.:
set IMIE=Jan
Po drugie, gdziekolwiek w pliku wsadowym, w dowolnym poleceniu można umieścić zapis %ZMIENNA%
, który jest podmieniany na zawartość zmiennej środowiskowej o danej nazwie. Za pomocą tego mechanizmu można wyświetlić daną zmienną:
echo Mam na imie %IMIE%.
Powyższe polecenie zostanie przed wykonaniem zamienione na echo Mam na imie Jan.
. Taki sposób działania prowadzi do możliwości wykonania skoku do etykiety o nazwie wziętej ze zmiennej, a nawet wykonania całego polecenia pamiętanego w zmiennej środowiskowej. Tekst ze zmiennej może być wykorzystany jako parametr dowolnego polecenia. Nas interesują jednak działania na samych zmiennych. Można się już domyślić, jak przypisać zmiennej wartość innej zmiennej:
set B=%A%
A poniższe polecenie połączy ze sobą dwa ciągi z dwóch zmiennych:
set SKLEJONE=%A%%B%
To już można wykorzystać do zrealizowania działań arytmetycznych. Jeżeli będziemy reprezentować liczby jako ciągi jakiegoś znaku powtórzonego ileś razy, np. III
zamiast 3 albo IIIIIIIIII
zamiast 10, to połączenie napisów będzie równoważne ich dodaniu. Zwiększenie liczby o stałą wartość to dopisanie określonej ilości znaków, np. set LICZNIK=%LICZNIK%I
zwiększy zmienną LICZNIK o 1.
Jak porównać ze sobą takie liczby? Polecenie IF
jedynie porównuje ze sobą dwa teksty (oraz sprawdza istnienie plików, ale to nic nam nie da). Zatem, jeśli chodzi nam wyłącznie o test równości dwóch liczb, wystarczy porównać je jako teksty. Porównanie odróżniające mniejszość od większości jest trudniejsze i wymaga pętli. Algorytm jest następujący:
Już widać, że te wszystkie działania szybkie nie będą. Odejmowanie przebiega następująco:
Taka reprezentacja liczb jest bardzo niewygodna do przetwarzania jej na komputerze, a co dopiero dla człowieka. Musimy więc opracować procedury zamiany liczby dziesiętnej na tę reprezentację wewnętrzną i odwrotnie. Odbywa się to poprzez zdefiniowanie trzech zmiennych dla cyfry setek, dziesiątek i jedności, a następnie inkrementowania postaci dziesiętnej, dopóki nie będzie równa liczbie dziesiętnej z wejścia. Równolegle liczymy potrzebne inkrementacje w postaci wewnętrznej. Zamiana odwrotna wygląda podobnie.
Program wyznaczania NWD będący zastosowaniem wszystkiego, co opisane powyżej ma 146 wierszy: https://gist.github.com/Jan-Mleczko/716aa27e1602fd6a110e0c604d498399 Działa, ale obliczenie NWD z 123 i 456 zajęło mu 6 sekund na laptopie Dell Latitude E6510 pod Windows 7, chociaż oczywiście program działa także pod DOS-em, bo nie używa windowsowych rozszerzeń, które inaczej byłyby dostępne i mocno by wszystko uprościły. Można to sprawdzić albo za pomocą DOSBox-a, albo wyłączając rozszerzenia poleceniem cmd /E:OFF
.
@andrzejlisek: dotąd, to ani nie udowodniono, ani nie obalono kompletności języka plików wsadowych w sensie Turinga.
wat? Literalnie pierwszy link z google prowadzi do so, a tam jest dowód https://github.com/yyny/Brainfuck-In-Batch
Taka ciekawostka (czytaj do końca): Dzięki nazwie specjalnej ..
da się tworzyć długie, "włóczące się" ścieżki do plików. Na przykład przy takiej strukturze katalogów:
E:.
├───test1
│ │ plik.txt
│ │
│ └───test3
└───test2
Będzie działało polecenie
type e:\test1\test3\..\..\test2\..\test1\plik.txt
Co ciekawe katalogi test2
ani test3
wcale nie muszą istnieć! Oznacza to, że Windows wykonuje jakieś upraszczanie ścieżek przed sięgnięciem na dysk. Tak samo robi DOS, ale UNIX już nie.
Koledzy chyba nie potrafią znieść krytyki lub przynajmniej czytać swoich własnych wypowiedzi ze zrozumieniem XD Szkoda, bo liczyłem na odrobinę merytorycznej dyskusji, ale jak widać przeliczyłem się. W sumie to czego ja oczekuję od programistów ograniczających swoje horyzonty do PHP i Delphi :( Oby tylko koledzy się kiedyś na .
nie przejechali, bo będzie smutek :(
Nie jest to wiedza bezużyteczna, bo czasami ścieżki są sklejane - podajemy ścieżkę względem jakiegoś miejsca w drzewie, i wiemy że coś będzie do tej ścieżki doklejone. Wiedza że ..
oznacza katalog wyżej, a .
katalog bieżący może się tu przydać. Nie wiem jak w unixach, ale pod Windows można zrobić też np. c:\foo\.\.\.\bar
i to jest to samo co c:\foo\bar
Squirrel - mój superset DOSowych wildcardów z implementacją w C
Ponieważ bardzo podoba mi się składnia DOSowych wildcardów, postanowiłem zaimplementować je w C pod nazwą Squirrel. Gdy biblioteka była gotowa, pomyślałem jednak, że warto byłoby dodać dwa nowe metaznaki. Po pierwsze, +
oznaczający jeden znak (jako alternatywa dla ?
, który dopasowuje jeden znak lub puste dopasowanie) a po drugie #
oznaczający cyfrę dziesiętną. Dziękuję @elwis i @Patryk27 za uwagi w sprawie implementacji.
https://github.com/Manna5/Squirrel
GitHub is where people build software. More than 56 million people use GitHub to discover, fork, and contribute to over 100 million projects.
https://github.comAle w DOSie pojedyncza gwiazdka dopasowywała ukośnik, a nie mogę zmienić jej znaczenia bo wtedy przestał by być to superset. Natomiast wprowadzę dwie gwiazdki jako niedopasowujące ukośników.
Jak dotąd, to ani nie udowodniono, ani nie obalono kompletności języka plików wsadowych w sensie Turinga. W bardzo dawnych czasach to właśnie próbowałem coś tworzyć za pomocą plików BAT. Wtedy wykorzystywałem głównie etykiety, GOTO, CLS, ECHO, SET i CHOICE (był program choice.com dołączony do DOS, to nie było polecenie wbudowane w command.com). Miałem z jakiejś gazety prymitywną gierkę będącą labiryntem. Cała gra, to była tak naprawdę lista możliwych stanów i naciskając klawisze przechodziło się między stanami, nic więcej nie było. Każdy stan, to było wymazanie EKRANU CLS, potem wypisanie ECHO i zapytanie o klawisz za pomocą CHOICE, potem przejścia do etykiet w zależności od naciśniętego klawisza.