2013-06-21 8 views
11

अगर में काम नहीं कर बदलाव जब मैं एक IF ब्लॉक के मैं कुछ अप्रत्याशित परिणाम दिखाई दे रही है अंदर SHIFT उपयोग करने के लिए प्रयास करें। इस का उपयोग करते हुए:विंडोज बैच ब्लॉक

@echo off 

if "%1"=="/p" (
    echo %1 
    shift 
    echo "shifted" 
    echo %1 
) 

मैं निम्नलिखित मिल:

C:\>ex.bat /p HAI 
/p 
"shifted" 
/p 

हालांकि, जब मैं इस कोड का उपयोग करें:

C:\>ex.bat /p HAI 
/p 
"shifted" 
HAI 

मैं की जरूरत है:

@echo off 

echo %1 
shift 
echo "shifted" 
echo %1 

मैं इस मिल दूसरा आउटपुट, लेकिन एक लॉजिक ब्लॉक में, इसलिए मैं लूप ओव कर सकता हूं आर मैं जॉन के जवाब यहाँ करने के लिए कुछ इसी तरह लागू करने के लिए कोशिश कर रहा हूँ: Using parameters in batch files at DOS command line, लेकिन मैं कुछ समस्या हो रही है। ये क्यों हो रहा है?

+0

मैंने यहां जवाब ढूंढने का अंत किया: [शिफ्ट बैच स्क्रिप्ट में काम नहीं करता है] (http://social.technet.microsoft.com/Forums/scriptcenter/en-US/7bbbe8df-e3c0-46ab-aede-396c2b6f6184/shift-doesnt-work-in-batch-script) – piebie

उत्तर

10

यह अपेक्षित व्यवहार है क्योंकि %1 लाइन को पारदर्शी होने पर विस्तारित किया जाता है, और संपूर्ण कोष्ठकित IF निर्माण को एक ही पास में पार्स किया जाता है। तो अगर आप एक नई लाइन तक शिफ्ट पार्स किया गया है, जो जब तक आप अपने parenthesized ब्लॉक छोड़ दिया है के बाद नहीं होगा का परिणाम नहीं देख सकते हैं।

%var% का उपयोग करते हुए पर्यावरण चर का विस्तार करते समय भी वही समस्या होती है। वातावरण चर के साथ आप देरी विस्तार को सक्षम करने SETLOCAL EnableDelayedExpansion का उपयोग कर और फिर !var! का उपयोग करके समस्या को हल कर सकते हैं। लेकिन देरी से विस्तार का उपयोग कर पैरामीटर का विस्तार करने के लिए कोई तुलनीय तरीका नहीं है।

संपादित करें 2013-06-21 - तुलनात्मक तरीका नहीं है, लेकिन अपेक्षाकृत धीमी गति से एक आसान तरीका है।

आप लाइन मजबूर कर सकते हैं कॉल का उपयोग करने और % अप में दोगुना होकर reparsed किया जाना है।

@echo off 

if "%1"=="/p" (
    echo %1 
    shift 
    echo "shifted" 
    call echo %%1 
) 



संपादित 2016-07-15 code in Vladislav's answer, एक बुरी बात है के रूप में यह संकेत मिलता है कि आप के बाद आप इसे छोड़ने के लिए गोटो इस्तेमाल किया कोड का एक खंड के अंदर वापस जा सकते हैं। यह बस काम नहीं करता है। गोटो तुरंत किसी भी पार्स कोड कोड को मारता है। साथ ही आप व्लादिस्लाव के कोड लिखा हो सकता है के रूप में:

@echo off 
if "%1"=="/p" (
    goto :true 
    :true 
    echo "%1" 
    shift 
    echo shifted 
    echo "%1" 
) 

अगर हालत गलत है, तो पूरे ब्लॉक को छोड़ दिया है। यदि स्थिति सत्य है, तो GOTO तुरंत ब्लॉक को मारता है, और फिर निष्पादन सामान्य रूप से: वास्तविक लेबल (कोई ब्लॉक संदर्भ नहीं) पर उठाता है। अंत में अतिरिक्त ) को अनदेखा किया जाता है।

ध्यान दें कि आप इस निर्माण के साथ एक और नहीं जोड़ सकते हैं।

@echo off 
if "%1"=="/p" (
    goto :true 
    :true 
    echo "%1" 
    shift 
    echo shifted 
    echo "%1" 
) else (
    echo This will execute regardless whether arg1 is /p or not 
) 

गलत है, तो केवल और ब्लॉक निष्पादित होता है: निम्न वांछित परिणाम नहीं देता है। यदि सही है, तो शीर्ष ब्लॉक निष्पादित किया जाता है और तुरंत मार दिया जाता है। कोड का शेष निष्पादित किया गया है, और ) else ( लाइन को अनदेखा किया गया है क्योंकि ) कार्य एक आरईएम के रूप में यदि पार्सर कमांड की अपेक्षा कर रहा है और स्टैक पर कोई सक्रिय कोष्ठक ब्लॉक नहीं हैं।

मैं दृढ़ता से अनुशंसा करता हूं कि आपने कभी भी ऊपर दिखाए गए कोड के एक कोष्ठक ब्लॉक के भीतर एक लेबल नहीं मिला (या जैसा कि Vladislav किया गया है)।

@echo off 
if not "%1"=="/p" goto :skip 
echo "%1" 
shift 
echo shifted 
echo "%1" 

:skip 

आप और कुछ अतिरिक्त लेबल के साथ एक IF/फिर/और अवधारणा का समर्थन कर सकता है gotos

@echo off 
if not "%1"=="/p" goto :notP 
echo "%1" 
shift 
echo shifted 
echo "%1" 
goto :endIf 

:notP 
echo not /p 

:endIf 
2
:

नीचे एक ही बात करने के लिए एक बेहतर (सरल और भ्रामक नहीं) तरीका है

वास्तव में आप ब्लॉक के बाहर केवल शिफ्ट कर सकते हैं:

@echo off 
if "%1"=="/p" (
    echo "%1" 
    goto:perform_shift; 
:aftersift 
    echo "%1" 
) 
goto:end; 

:perform_shift 
shift 
echo "shifted" 
goto:aftersift; 


:end 
+1

वह "कामों का प्रकार", लेकिन यह बहुत बुरा रूप है। इसका तात्पर्य है कि आप एक कोष्ठक ब्लॉक के भीतर कूद रहे हैं, जो काम नहीं करता है। जिस क्षण आप ब्लॉक के भीतर गोटो का उपयोग करते हैं, आप ब्लॉक को मार देते हैं; कोष्ठक वहां हैं, लेकिन वे कोई उद्देश्य नहीं देते हैं। यह इस मामले में महत्वपूर्ण नहीं है, लेकिन यदि ब्लॉक फॉर लूप का हिस्सा है तो बहुत महत्वपूर्ण है। यदि आप फॉर लूप के भीतर जाते हैं, तो लूप मारे जाते हैं। – dbenham

+0

देखें [मेरे उत्तर में 2016-07-15 संपादित करें] (http://stackoverflow.com/a/17241649/1012053) अधिक जानकारी के लिए कि यह उत्तर एक अच्छा विचार क्यों नहीं है, साथ ही बेहतर के लिए एक सुझाव प्रभावी ढंग से एक ही काम करने का तरीका। – dbenham

संबंधित मुद्दे