".Bat" dosyasında komut satırı parametresi nasıl kontrol edilir?


104

İşletim sistemim Windows Vista. Kullanıcının herhangi bir komut satırı parametresi girip girmediğini kontrol etmem gereken bir ".bat" dosyasına ihtiyacım var. Eğer öyleyse, eğer parametre eşitse -bo zaman bir şeyler yapacağım, aksi takdirde "Geçersiz girdi" işaretleyeceğim. Kullanıcı herhangi bir komut satırı parametresi girmezse bir şeyler yapacağım. Aşağıdaki .bat dosyasını oluşturdum. Durumlar için çalışır -bve eşit değildir -b- ancak kullanıcı herhangi bir komut satırı parametresini geçmediğinde başarısız olur.

Her zaman hata alıyorum:

GOTO was unexpected at this time.

Biri bana burada neyi yanlış yaptığımı söyleyebilir mi?


ECHO OFF
CLS
ECHO.

IF [%1]==[/?] GOTO BLANK

IF %1=="-b" GOTO SPECIFIC

IF NOT %1=="-b" GOTO UNKNOWN

:SPECIFIC

ECHO SPECIFIC

GOTO DONE

:BLANK

ECHO No Parameter

GOTO DONE

:UNKNOWN

ECHO Unknown Option

GOTO DONE

:DONE

ECHO Done!

GOTO BLANKDiğer iki IFifadeye köşeli parantez ( satırdaki gibi) eklerseniz , bu sorunu çözer mi?
Yeremya Willcock

Yanıtlar:


141

Parametrenin boş olup olmadığını kontrol etmeniz gerekir: if "%~1"=="" goto blank

Bunu yaptıktan sonra, if / else anahtarını açın -b: if "%~1"=="-b" (goto specific) else goto unknown

Parametreleri tırnak işaretleriyle çevrelemek, boş / boş / eksik parametreler gibi şeyleri kontrol etmeyi kolaylaştırır. "~", komut satırı bağımsız değişkeninde iseler çift tırnakların kaldırılmasını sağlar.


Bu çalışıyor!! Yalnızca "başka" kabul edilmez. Hata alıyorum: 'else' dahili veya harici bir komut, çalıştırılabilir program veya toplu iş dosyası olarak tanınmıyor. Bu yüzden "-b'ye eşit değildir" durumu için başka bir EĞER ekledim. Hızlı cevap için teşekkürler.
javauser71

7
ELSE, IF ile aynı satırda olmalı veya bir parantezin hemen sonrasında olmalıdır
jeb

4
% 1 boşluk içeriyorsa, bu benim için işe yaramıyor gibi görünüyor, bu, bir yürütülebilir dosyanın tam yolu ise bu durum söz konusu olabilir. Değerlerinde boşluk bulunan parametreler için bile çalışan bir çözüm için Jeremiah Willcock'un cevabına bakın .
Mark A. Fitzgerald

argümanınız a ise kabul edilmeyecektir File, bu durumda yalnızca existveya işaretiniz olmalıdır not exist. Bu nedenle argümanlarınız iyi tanımlanmış olmalı veya sadece powershell veya vbScript kullanmalıdır (80'lerde iseniz ..)

1
Bu başarısız olur run.bat "a b". "%1"==""arg'de boşluk varsa çöker. Bkz stackoverflow.com/a/46942471
wisbucky

27

Bir yanıt için http://ss64.com/nt/if.html adresine bakın ; komut IF [%1]==[] GOTO NO_ARGUMENTveya benzeri.


1
Bu AYRICA işe yaramaz! Aksine, sadece çalışır "%1"=="". Bunu kendi cevabımda detaylandırmalıyım.
Tomasz Gandor

1
bu,% 1 alıntı yapıldığında kırılacaktır, örneğin foo.bat "1st parameter" 2nd_param. Stackoverflow.com/questions/2541767/… sayfasına
matt wilkie

[%1]==[-b]Arg belirtilmişse kullanmak eşleşmez. Örnek run.bat "-b". Bkz stackoverflow.com/a/46942471
wisbucky

20

Kısa cevap - köşeli parantez kullanın:

if [%1]==[] goto :blank

veya (alıntılanan bağımsız değişkenleri işlemeniz gerektiğinde, aşağıdaki Düzenleme'ye bakın):

if [%~1]==[] goto :blank

Neden? sorabilirsin. Tam da Jeremiah Willcock'un bahsettiği gibi: http://ss64.com/nt/if.html - bunu kullanıyorlar! Tamam, ama alıntıların nesi var?

Yine, kısa cevap: "sihirli" - bazen çift (çift) tırnaklar tek (çift) tırnağa dönüştürülür. Ve başlangıç ​​için eşleşmeleri gerekiyor.

Şu küçük senaryoyu düşünün:

@rem argq.bat
@echo off

:loop 
if "%1"=="" goto :done
echo %1
shift
goto :loop

:done
echo Done.

Hadi test edelim:

C:\> argq bla bla
bla
bla
Done.

Çalışıyor gibi görünüyor. Ama şimdi ikinci vitese geçelim:

C:\> argq "bla bla"
bla""=="" was unexpected at this time.

Boom Bu doğru olarak değerlendirilmedi, yanlış olarak da değerlendirilmedi. Senaryo ÖLÜLDÜ. Reaktörü hattın aşağısında bir yerde kapatmanız gerekiyorsa, iyi şanslar. Artık Harry Daghlian gibi öleceksin.

Düşünebilirsiniz - Tamam, argümanlar tırnak içeremez. Yaparlarsa, bu olur. Yanlış İşte biraz teselli:

C:\> argq ""bla bla""
""bla
bla""
Done.

Ah evet. Endişelenmeyin - bazen bu işe yarayacaktır.

Başka bir komut dosyası deneyelim:

@rem args.bat
@echo off

:loop 
if [%1]==[] goto :done
echo %1
shift
goto :loop

:done
echo Done.

Yukarıdaki durumlarda iyi çalıştığını kendiniz test edebilirsiniz. Bu mantıklı - alıntıların parantezlerle hiçbir ilgisi yok, bu yüzden burada sihir yok. Peki ya değiştirgeleri parantezlerle süslemeye ne dersiniz?

D:\>args ]bla bla[
]bla
bla[
Done.

D:\>args [bla bla]
[bla
bla]
Done.

Orada şans yok. Parantezler, cmd.exe'ın ayrıştırıcısını boğamaz.

Bir an için kötü sözlere geri dönelim. Tartışma bir alıntıyla sona erdiğinde sorun oradaydı:

D:\>argq "bla1 bla2"
bla2""=="" was unexpected at this time.

Ya ben geçersem:

D:\>argq bla2"
The syntax of the command is incorrect.

Komut dosyası hiç çalışmayacak. Aynı args.bat:

D:\>args bla2"
The syntax of the command is incorrect.

Ama "böyle bir durumda -karakterlerin sayısı "eşleştiğinde" (yani - çift olduğunda) ne elde ederim :

D:\>args bla2" "bla3
bla2" "bla3
Done.

GÜZEL - .batDosyaların komut satırı argümanlarını nasıl böldüğü hakkında bir şeyler öğrenmişsinizdir umarım (İPUCU: * Bu tam olarak bash'daki gibi değildir). Yukarıdaki argüman bir boşluk içerir. Ancak alıntılar otomatik olarak silinmez.

Ve argq? Buna nasıl tepki veriyor? Tahmin edilebileceği gibi:

D:\>argq bla2" "bla3
"bla3"=="" was unexpected at this time.

Öyleyse - şunu söylemeden önce düşünün: "Ne olduğunu biliyor musunuz? Sadece alıntı kullanın. [Çünkü bana göre bu daha güzel görünüyor]".

Düzenle

Son zamanlarda, bu yanıtla ilgili yorumlar yapıldı - yani, köşeli parantezler, alıntılanan argümanları "aktaramaz" ve onlara alıntı yapılmamış gibi davranır.

Sözdizimi:

if "%~1"=="" (...)

Çift tırnaklar için yeni bulunan bir erdem değil, ilk ve son karakter bir çift tırnak ise, bağımsız değişken değişkeninden tırnakları çıkarmanın düzgün bir özelliğinin göstergesidir.

Bu "teknoloji", köşeli parantezlerle de aynı şekilde çalışır:

if [%~1]==[] (...)

Bunu belirtmek faydalı bir şeydi, bu yüzden yeni yanıta da olumlu oy verdim.

Son olarak, çift alıntı hayranları, ""kitabınızda formun bir argümanı var mı yoksa boş mu? Sadece soruyorum' ;)


1
[%1]==[-b]Arg gibi tırnak içine alınırsa köşeli parantezler eşleşmez run.bat "-b". Bkz stackoverflow.com/a/46942471
wisbucky

Tarihsel not: [%1]==[-b]ve "%1"=="-b"kazanmak 98 ve önceki MS / PC-DOS sistemleri toplu komut dosyaları için aynıydı. Win 2000 / NT if "%~1"=="-b", çift tırnakların özel bir anlama sahip olduğu sözdizimini tanıttığından beri , daha sağlam koruma sağladığı için komut dosyalarını kodlamanız gereken yol budur. Çift tırnak işaretleri, özel karakterlerin anlamından kaçar (komut satırınızda deneyin & | ve% karakter). Örneklerin% 99,9'u çift tırnak sözdizimiyle çalışır - örneğiniz argq bla2" "bla3yalnızca köşeli parantezleri yaslamak için büyük / küçük harftir. Yerleşik çift tırnaklar felaket için bir reçetedir - sadece şunu söyleyin
R'yi atlayın

@SkipR - bu yüzden Windows'un dosya sistemlerinde bu özel karakterleri isimlerde bulunduramazsınız. Matematiksel bir kanıtım yok, ama bence her şey cmdkabukta alıntılanamaz (yani - bir kaçış dizisi aracılığıyla kelimesi kelimesine yapılmış vs.) . Diğer sistemlerde bazen her şeyi alıntılayabilirsiniz, NUL karakteri dahil. ( stackoverflow.com/questions/2730732/… ) - bu soru sadece harici bir program kullanmanız gerektiğini gösterir.
Tomasz Gandor

8

Abone olduğum diğer cevaplara ek olarak /I, IFkomutun anahtarını kullanmayı düşünebilirsiniz .

... / I anahtarı, belirtilirse, büyük / küçük harfe duyarsız dize karşılaştırması yapılacağını söylüyor.

Kullanıcılarınıza parametreleri belirtme konusunda büyük / küçük harfe duyarlı olmayan bir esneklik vermek istemeniz yardımcı olabilir.

IF /I "%1"=="-b" GOTO SPECIFIC

5

Dizeleri karşılaştırıyorsunuz. Bir bağımsız değişken atlanırsa, %1bir boşluğa genişler, böylece komutlar IF =="-b" GOTO SPECIFICörneğin olur (bu bir sözdizimi hatasıdır). Dizelerinizi tırnak işaretleri (veya köşeli parantezler) içine alın.

REM this is ok
IF [%1]==[/?] GOTO BLANK

REM I'd recommend using quotes exclusively
IF "%1"=="-b" GOTO SPECIFIC

IF NOT "%1"=="-b" GOTO UNKNOWN

EĞER [% 1] == [/?] Çalışmıyorsa ama EĞER [% 1] == [] veya "% 1" == "" yaparsam çalışır. Neyse şimdi gidebilirim. Hızlı cevabın için teşekkürler.
javauser71

5

Aslında, diğer tüm cevapların kusurları var. En güvenilir yol şudur:

IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

Detaylı açıklama:

Kullanılması "%1"=="-b"alanlarda ve tırnak argüman geçen eğer düz dışarı çökmesine. Bu en az güvenilir yöntemdir.

IF "%1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat "a b"

b""=="-b" was unexpected at this time.

Kullanmak [%1]==[-b]daha iyidir çünkü boşluklar ve tırnaklarla çakışmaz, ancak bağımsız değişken tırnak içine alınmışsa eşleşmez.

IF [%1]==[-b] (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat "-b"

(does not match, and jumps to UNKNOWN instead of SPECIFIC)

Kullanmak "%~1"=="-b"en güvenilir olanıdır. %~1varsa çevreleyen alıntıları kaldırır. Bu nedenle, tırnak işaretli ve tırnaksız ve ayrıca bağımsız değişkenler olmadan çalışır.

IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)

C:\> run.bat
C:\> run.bat -b
C:\> run.bat "-b"
C:\> run.bat "a b"

(all of the above tests work correctly)

1
Bu köşeli parantezlerin sonu değil, görüyorsunuz: IF [%~1]==[]- bu işe yarıyor ve hatta işliyor "-b". Sadece kutunun içinde , erm, kare [parantez] içinde düşünebilmeniz gerekir .
Tomasz Gandor

3

Son zamanlarda karmaşık parametre anahtarlarının bir toplu iş dosyasında uygulanmasıyla mücadele ediyorum, bu yüzden işte araştırmamın sonucu. Verilen yanıtların hiçbiri tam olarak güvenli değil, örnekler:

"%1"=="-?" Parametre tırnak işaretleri içine alınmışsa eşleşmez (dosya adları vb. için gereklidir) veya parametre tırnak işaretleri içindeyse ve boşluklar içeriyorsa (yine dosya adlarında sıklıkla görülür) kilitlenir

@ECHO OFF
SETLOCAL
echo.
echo starting parameter test...
echo.
rem echo First parameter is %1
if "%1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
C:\>test.bat -?

starting parameter test...

Condition is true, param=-?

C:\>test.bat "-?"

starting parameter test...

Condition is false, param="-?"

Köşeli parantez içeren herhangi bir kombinasyon [%1]==[-?]veya [%~1]==[-?]parametrenin tırnak içinde boşluk olması durumunda başarısız olur:

@ECHO OFF
SETLOCAL 
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if [%~1]==[-?] (echo Condition is true, param=%1) else (echo Condition is false, param=%1)

C:\>test.bat "long file name"

starting parameter test...

First parameter is "long file name"
file was unexpected at this time.

Önerilen en güvenli çözüm "%~1"=="-?", tırnak işaretleri dışındaki metinleri ve tırnak içindeki boşlukları içeren metni içeren karmaşık bir parametreyle çökecektir:

@ECHO OFF
SETLOCAL 
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if "%~1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)

C:\>test.bat -source:"long file name"

starting parameter test...

First parameter is -source:"long file name"
file was unexpected at this time.

Yukarıdaki tüm senaryoların kapsanmasını sağlamanın tek yolu, EnableDelayedExpansion'ı kullanmak ve parametreleri, değişkenler kullanarak referansla (değere göre değil) geçirmektir. O zaman en karmaşık senaryo bile iyi çalışacaktır:

@ECHO OFF
SETLOCAL EnableDelayedExpansion
echo.
echo starting parameter test...
echo.
echo First parameter is %1
:: we assign the parameter to a variable to pass by reference with delayed expansion
set "var1=%~1"
echo var1 is !var1!
:: we assign the value to compare with to a second variable to pass by reference with delayed expansion
set "var2=-source:"c:\app images"\image.png"
echo var2 is !var2!
if "!var1!"=="!var2!" (echo Condition is true, param=!var1!) else (echo Condition is false, param=!var1!)
C:\>test.bat -source:"c:\app images"\image.png

starting parameter test...

First parameter is -source:"c:\app images"\image.png
var1 is -source:"c:\app images"\image.png
var2 is -source:"c:\app images"\image.png
Condition is true, param=-source:"c:\app images"\image.png

C:\>test.bat -source:"c:\app images"\image1.png

starting parameter test...

First parameter is -source:"c:\app images"\image1.png
var1 is -source:"c:\app images"\image1.png
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images"\image1.png

C:\>test.bat -source:"c:\app images\image.png"

starting parameter test...

First parameter is -source:"c:\app images\image.png"
var1 is -source:"c:\app images\image.png"
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images\image.png"

0

Windows toplu işleminde bunu yapmak için TANIMLANAN anahtar sözcük vardır.

IF DEFINED %~1 foo
IF NOT DEFINED %~1 bar

Teşekkür ederim David. EĞER ve EĞER DEĞİL arasında neden bir satır başı ve yeni satır olamadığını bilmiyorum. Fark etmedim bile.
Charles
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.