Co oznacza łącznik w pliku wsadowym systemu Windows?


1

W szczególności mam problemy ze zrozumieniem łączników w następujących wierszach, które pochodzą z wikibooks

if not -%1-==-- echo Argument one provided
if -%1-==-- echo Argument one not provided & exit /b

Aby sprawdzić, czy zmienna istnieje lub jest zdefiniowana, są zasadniczo dwa sposoby, których nauczyłem się tutaj :

IF DEFINED MyVar (ECHO MyVar IS defined) ELSE (ECHO MyVar is NOT defined)

IF "%MyVar%"=="" (ECHO MyVar is NOT defined) ELSE (ECHO MyVar IS defined)

Więc co (1) łączniki wokół argumentu% 1 i (2) łączniki po znaku ==?


1
jeden z twoich komentarzy wspominał %%, który jest używany w pętli for w pliku wsadowym, takim jak %% f, nie dla parametrów wiersza polecenia wsadowego% 1% 2% 3. Z wiersza poleceń możesz to zrobić, for %1 in (*.*) do @echo %1a byłoby to dwuznaczne, aby zrobić to w pliku wsadowym, więc w przypadku instrukcji znajdujących się w pliku wsadowym użyj %%, ale parametry wsadowe (które są zawsze tylko w pliku wsadowym) to zawsze% 1 ,% 2 itd.
— barlop

Drogi midnite: Jest rok 2015. Dlaczego nadal używasz języka programowania tak kiepskiego jak skrypty wsadowe? Możesz przełączyć się na VBScript, JScript, PowerShell lub jedną z wielu innych opcji .
— niezapomniany

„Jednak wymagają one zainstalowania interpretera języka skryptowego, zanim będzie można go użyć” - bez szkody, aby dowiedzieć się więcej, szczególnie działa on natywnie na większości komputerów ;-)
— midnite

1
@midnite Chyba wsadowo, istnieje limit liczby problemów, na które możesz natknąć się. Więc nauczyłem się przez lata, pytając i bawiąc się. I wydaje się, że są geniusze, którzy wymyślili rzeczy, które nie zostały zapisane w żadnych odnośnikach, kiedy robi się naprawdę trudny. Na przykład .. dave benham i jeb .. Myślę, że oba posty tutaj, a także na forum dostips .. A jeśli chodzi o odniesienie, jest oryginalny vfrazee.com/ms-dos/6.22/help, który pojawił się w DOSie podczas uruchamiania HELP.COM (możesz kliknąć np. JEŻELI następnie przykłady), a tam jest ss64.com/nt
— barlop

1
te małe programy C mogą pomóc pokazać, jak programy dzielą rzeczy na parametry, aby pomóc w rozwiązywaniu problemów z cudzysłowami superuser.com/questions/944745/sed-command-with-apostrophe/... A jeśli kiedykolwiek zwariowałeś, to napisali jeb i dbenham posty o tym, jak działa interpreter wsadowy .. znalezione poprzez przetestowanie go, a nie inne referencje stackoverflow.com/questions/4094699/...
— barlop

Odpowiedzi:


6

Rozważ to

C:\>if not -%1-==-- echo Argument one provided
Argument one provided

C:\>if not P%1P==PP echo Argument one provided
Argument one provided

Powinno być oczywiste, że znak minus / łącznik jest po prostu używany do ułatwienia wyznaczenia pustej wartości. Ten konkretny symbol nie ma specjalnego znaczenia w tym wyrażeniu - jest traktowany jak każdy inny nietypowy znak.

Możemy dodać spacje, aby wyjaśnić, że ==operator nie jest modyfikowany przez otaczające znaki

C:\>if not P%1P == PP echo Argument one provided
Argument one provided

Zasadniczo lepiej jest stosować konwencjonalne podejścia, które więcej osób zrozumie od razu (np. Użycie znaków cudzysłowu).

C:\>if not "%1"=="" echo Argument one provided
Argument one provided

W przypadku systemu DOS i być może wczesnych wersji systemu Windows uważam, że wystąpiły pewne problemy (których nie pamiętam) przy użyciu znaków cudzysłowu, które doprowadziły do ​​tego, że ludzie używali w ten sposób znaków do wydruku. Nie próbowałem przypadku, w którym% 1 zawiera na przykład znak cudzysłowu.


Widzę. Dziękuję bardzo. Czyli w gruncie rzeczy oznacza to konkatenację dwóch znaków przed i za zmienną, prawda? OTOH, próbowałem użyć definedsłowa kluczowego, aby sprawdzić, czy parametr istnieje. Oba IF DEFINED %1i IF DEFINED %%1wydają się nie działać. Czy dałbyś mi jakieś wskazówki?
— midnite

Piszesz „znak minus / myślnik jest po prostu używany do uproszczenia oznaczenia pustej wartości” <--- słowo „upraszczaj” prawdopodobnie nie jest dobrym słowem do użycia, ponieważ nie tylko upraszcza ( jakiekolwiek uproszczenie oznaczałoby). Ale jak wiadomo, zapobiega to błędom, gdy nie podano żadnego argumentu.
— barlop

@barlop: Dzięki za komentarz. Odpowiedź edytowana.
— RedGrittyBrick

Dobra edycja, ale na końcu napisałeś: „Z DOS i być może wczesnymi wersjami Windows, myślę, że były pewne problemy (których nie pamiętam) z użyciem znaków cudzysłowu” <- Nadal są. ponownie używam „% 1”, zobacz moją odpowiedź. Początkowo powiedziałem, że cytaty były świetne w okolicy% 1, potem supercat, skomentował i poprawiłem to.
— barlop

Piszesz „nie próbowałem przypadku, w którym% 1 zawiera na przykład znak cudzysłowu”. <- Jeśli użytkownik je dostarczy, a ty nie zrobisz "% 1", to dobrze. Jeśli użytkownik je dostarczy i dodasz je „% 1”, to nie w porządku
— barlop

4

Jest to ważne, gdy używasz% 1 do umieszczenia czegoś wokół niego, aby zapobiec zerwaniu pliku wsadowego, gdy% 1 jest pusty, ponieważ% 1 nie jest zmienną, zostaje podstawiona wartością, jak np. Wstrzyknięcie SQL jako przykład wstrzyknięcia wsadowego i gdy wartość jest niczym, a% 1 jest w JEŻELI, wtedy zostaje uszkodzony kod. if %1==""staje się if == ""i daje błąd.

Jeśli chodzi o to, dlaczego jeśli zdefiniowane nie działa na% 1,% 1 jest wartością, a nie zmienną, więc zdefiniowane tam nie działa. Aby kod działający dla% 1 był pusty, potrzebujesz kodu, który nie ulegnie uszkodzeniu, gdy% 1 zostanie zastąpiony niczym. Spróbuj if "%1"=="" lub spróbujif [%1]==[]

Można powiedzieć, że% 1 wygląda trochę myląco, nie wygląda mi to na dobrą konwencję! Technicznie można nawet zrobić if a%1==a%1 albo if %1a==%1aale konwencja wydaje się być[]

Możesz użyć cudzysłowów, [] lub dowolnych znaków. Ale jak zauważył supercat w komentarzu, cytaty nie są dobrym pomysłem w przypadku% 1. (Ponieważ jeśli% 1 zawiera spacje, użytkownik dołącza cudzysłowy do tego, co zostaje przekazane jako% 1, a jeśli jest% w spacji i w pliku wsadowym wstawiasz cudzysłowy wokół% 1, cytaty zostaną anulowane i niecytowane miejsce spowoduje błąd).

Jeśli robisz IF w wierszu poleceń i nie testujesz żadnej zmiennej, nie masz% 1 i nawet nie potrzebujesz []. Powiedziałbyś IF "a b c"=="a b c" echo a lub IF a==b echo a Jeśli w pliku wsadowym często masz% 1, a zamiast cudzysłowów wokół% 1, użyj np. Jednego lub dwóch znaków np. [%1]I użyj cudzysłowów, jeśli chcesz zachować spacje i nie jest to% 1 egeg IF [%1]==[a]lub IF [%1]==["a b"] echo aNie rób, "%1"ponieważ% 1 może już zawierać cytaty, które zostaną anulowane, a następnie, jeśli% 1 ma spację, instrukcja if łamie się.

Jeśli byłeś w linii poleceń i testowałeś zmienną, to zależy od tego, czy zmienna ma cudzysłowy. Możesz spojrzeć na zawartość.

Zmienna może mieć spację i nie zawierać cudzysłowów.

Tak więc w tym konkretnym przypadku wiersza polecenia, umieszczanie cudzysłowów w okolicach% a% nie spowoduje podwójnego cudzysłowu, a jeśli chcesz przetestować względem „a b”, musisz wstawić cudzysłowy wokół% a%

C:\>set a=a b

C:\>echo %a%
a b

C:\>IF %a%=="a b" echo sdf
b=="a b" was unexpected at this time.

C:\>IF "%a%"=="a b" echo sdf
sdf

So ^^^ we want "%a%"

Podczas gdy jeśli% a% zawierałby cudzysłowy, byłby to inny przypadek

C:\>set a="a b"

C:\>echo %a%
"a b"

C:\>IF %a%=="a b" echo a
a

C:\>IF "%a%"=="a b" echo a
b""=="a b" was unexpected at this time.

C:\>

^^^^ So there we want %a% without quotes around it.

Wszystko więc zależy od tego, czy zmienna lub parametr zawiera cudzysłowy. Jeśli% 1 ma spacje, będzie zawierał cudzysłowy. Wiemy więc, że gdybyśmy porównali% 1 z „a b”, to w nie zrobiłby „% 1”. A gdyby% 1 nie zawierał cudzysłowów, nie zawierałby spacji, więc nie zrobilibyśmy „% 1”. Myślę, że nigdy nie chciałbyś robić „% 1”. Tak więc, jeśli% 1 zawiera spacje, w% 1 pojawią się cudzysłowy, a spacje zostaną już zachowane.

Przekreśliłem poniżej w świetle komentarza superkata. I dodałem więcej do mojego postu powyżej.

Cytaty są najlepsze w okolicach% 1, a nie [] lub niektórych znaków, takich jak A lub -, ponieważ na przykład jeśli użyjesz [], to nie zachowa spacji

C: \> if [dab] == [dab] echo sdf

w tym czasie było nieoczekiwane.

Powiedz, if "d a b"że to zadziała. Więc if "%1"jest lepszy niż inne postacie takie jak if [%1]lub a%1alub-%1


2
Jedynym sposobem %1będzie rozwinięcie się do czegoś zawierającego spacje, jeśli argument zawiera znaki cudzysłowu. W takim przypadku otoczenie %1ze znakami cudzysłowu spowoduje zepsute zachowanie, a otoczenie go czymś innym powinno działać.
— supercat

2
Co jeśli cytowany argument zawiera spacje?
— supercat

1
@supercat ah widzę, dobrze zauważony. if "" 2""==""2"" echo azawodzi. A na wypadek, gdyby nikt nie wiedział ... Efektem ""będzie włączenie lub wyłączenie cytowania.
— barlop

1
@midnite ma pewne podobieństwo do konkatenacji, którą widzisz w bardziej zaawansowanych językach, ale myślę, że funkcjonalnie nie tak bardzo, bo w java itp., konkatenacja składa się z dwóch oddzielnych jednostek, nawet jeśli wykonujesz „asdf” + „asdf”. Natomiast w cmd "asdf""asdf"nie łączy dwóch osobnych obiektów. Pierwszy „oznacza włączenie trybu, w którym zachowane są spacje i niektóre inne znaki. Następny” oznacza wyłączenie tego trybu. Następny włącza. Możesz więc powiedzieć „asdf asdf” lub powiedzieć „ asdf" "asdf Więc 2""nie powinno to wyglądać zbyt skomplikowane”. (ale czasem zastanawianie się, jak działa cmd / partia, jest trudne)
— barlop

1
@midnite także Wątpię, aby plik wsadowy (ogólnie) rozróżniał ciągi i liczby, chociaż niektóre polecenia lub funkcje w poleceniu tak. To, czy 2 jest liczbą, czy łańcuchem, zależy od interpretacji. Jeśli powiesz, że echo 2nie ma konwersji 2 na ciąg. Przypuszczam, że technicznie z komputerami wszystko to jest zakodowane (nie powiem znaków) zawijasy / glify. Niektórzy mogą spojrzeć na prezentację, jeśli są cytatami lub nie, a następnie potraktować ją odpowiednio jako liczbę (do obliczeń) lub ciąg znaków (w celu posortowania ich alfabetycznie). Lub tak jak zakodowane glify są to liczby lub ciągi znaków.
— barlop

1

Nie jestem pewien, czy to rozumiesz, więc pozwól mi zobaczyć, czy mogę to uprościć.

Załóżmy, że plik wsadowy otrzymuje wartość %1z wiersza poleceń i chcesz sprawdzić, czy jest to „kot” czy „pies”. Możesz to sprawdzić:

if %1 == cat goto CAT
if %1 == dog goto DOG
REM Default: Complain about no dog or cat
goto OOPS
:CAT
echo I'm a cat!
REM Successful, so skip to end
goto END
:DOG
echo I'm a dog!
goto END
:OOPS
echo I didn't see a cat or dog!
REM This just falls through to the end
:END

%1 zastępuje się tekstem kot lub pies (powiedzmy pies), więc tłumacz naprawdę to widzi:

if dog == cat goto CAT
if dog == dog goto DOG

Ale jeśli osoba uruchamiająca skrypt nie podała wartości w wierszu poleceń, interpreter zobaczy to:

if  == cat goto CAT
if  == dog goto DOG

To jest niepoprawna składnia i spowoduje błąd. Konwencja polega więc na tym, aby dołączyć 1 lub więcej znaków i najpierw sprawdzić brak zmiennej, coś takiego:

if %1* == * goto OOPS
REM If no value passed in, this is seen as  if * == *  which evaluates to true
if %1 == cat goto CAT
if %1 == dog goto DOG
goto END
:CAT
echo I'm a cat!
goto END
:DOG
echo I'm a dog!
goto END
:OOPS
echo You were supposed to include a type of pet!
:END

Jeśli %1nic nie zostanie ocenione, dodatkowe znaki są nadal dostępne, aby zachować poprawną składnię. Używam *, ale często pojawiają się cytaty lub wykrzykniki, takie jak "%1"lub %1!, a także łączniki, takie jak --%1lub -%1-itp.

Człowieku, nie mogę uwierzyć, że wciąż to wszystko pamiętam. :-) Mam nadzieję, że to pomoże!


Napisałeś „Ale jeśli osoba uruchamiająca skrypt nie zawierała zmiennej”, <- możesz mieć na myśli „wartość”, ponieważ jest to bardziej wartość niż zmienna. Przekazuje dane, może można powiedzieć wartość. A jeśli chodzi o sposób, w jaki to jest przekazywane, (w programowaniu niektórych bardziej zaawansowanych języków możesz mieć „pass by value” lub „pass by reference”. Myślę, że można by powiedzieć, że to jest przekazywane przez wstrzyknięcie!
— barlop

„możesz oznaczać„ wartość [zamiast zmiennej] ”… Ups! Masz rację!
— furry_marmot
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.