2017-06-22 8 views
5

मेरी previous प्रश्न पर काम करते हुए, मैं एक ऐसी ही मुद्दा यह है कि मैं शुरू में सुलझाने था सामना करना पड़ा।बैच - मनमाने ढंग से प्रतिशत-संख्या (% 1) या प्रतिशत-तारांकन (% *) तर्कों को सही तरीके से असाइन करने के लिए कैसे उद्धरण हो सकते हैं?

वास्तव में, मैं प्रयास में इस महीने के खर्च एक सार्वभौमिक .bat सहायक पुस्तकालय है कि के रूप में सबसे अच्छा के रूप में यह संभव है किसी भी नाम के साथ खींचें और गिरा दिया फ़ाइलों को संभाल लेंगे बनाने के लिए। मैं इसे कॉलर के लिए पारदर्शी रूप से करना चाहता हूं, और पिछली-किसी भी मौजूदा स्क्रिप्ट के साथ संगत, इसलिए फ़ाइल नाम% 1,% 2 के रूप में वितरित किए जाते हैं, और मुझे इसके साथ कोई समस्या नहीं है। @MCND की

समाधान %CMDCMDLINE% और फिर मुश्किल पार्स इसे पढ़ने के लिए है। तो मैं बस set "a=%CMDCMDLINE:"=?%" की तरह लिख सकता हूं - और पूर्ण स्ट्रिंग को चर ए में है, लेकिन अंदर के सभी उद्धरण तुरंत प्रश्न चिह्न ? के साथ प्रतिस्थापित किए जाते हैं, जिसके परिणामस्वरूप एक अनजान रेखा होती है जिसे मैं आसानी से आगे संसाधित कर सकता हूं।

लेकिन यह केवल .bat खींचें और ड्रॉप के लिए काम करता है, कि जिस तरह से मैं कमांड प्रॉम्प्ट से पारित पैरामीटर नहीं पढ़ सकते हैं के बाद से। मुझे %* का उपयोग करना है।

मेरा वर्तमान प्रश्न यह है कि: यदि पैरामीटर में उद्धरण वर्ण भी हो सकते हैं, यहां तक ​​कि unpaired भी इसे कैसे पढ़ा जाए?

पर विचार करें निम्नलिखित बैट फ़ाइल: (के कॉल "C: \ test.bat")

@echo off 
echo START 
setlocal enabledelayedexpansion 

set a=%1 
echo a=[!a!] 

set b="%1" 
echo b=[!b!] 

set "c=%1" 
echo c=[!c!] 

set d=%~1 
echo d=[!d!] 

set e="%~1" 
echo e=[!e!] 

set "f=%~1" 
echo f=[!f!] 

set g=%* 
echo g=[!g!] 

set h="%*" 
echo h=[!h!] 

set "i=%*" 
echo i=[!i!] 

endlocal 
echo DONE 
exit /b 

मूल रूप से यह है सब कुछ है कि मैं भेजे बैच को पढ़ने के लिए ("कॉल") प्रतिशत-पैरामीटर कल्पना कर सकते हैं: %1, %~1, %* unquoted set x=y में set "x=y" उद्धृत और स्पष्ट रूप से set x="y" भिन्नताओं को उद्धृत किया गया है। विलंबित विस्तार केवल मूल्य को सुरक्षित रूप से प्रतिबिंबित करने के लिए है (यहां मुझे सादगी के लिए पैरामीटर में परीक्षा अंक ! की परवाह नहीं है)।

मेरा अंतिम उद्देश्य एक ऐसी स्क्रिप्ट बनाना है जो कभी भी त्रुटि नहीं डालेगा: इसलिए मेरे कोड निष्पादन (सीएमडी प्रॉम्प्ट पर) होने से पहले या फिर समाप्त होने के बाद प्रत्येक संभावित त्रुटियां दिखाई देनी चाहिए (जब कॉलर पहुंचने का प्रयास करेगा एक टूटी हुई नाम वाली एक फाइल)।

तो इस उदाहरण में, स्टार्ट और डोन के बीच आदर्श रूप से कोई त्रुटि नहीं होनी चाहिए, लेकिन वे संबंधित "गूंज" से पहले "सेट" निर्देशों पर दिखाई देंगे।

प्रयास # 1

कमान: test

आउटपुट:

START 
a=[] 
b=[""] 
c=[] 
d=[] 
e=[""] 
f=[] 
g=[] 
h=[""] 
i=[] 
DONE 

अच्छा, नहीं शून्य तर्क पर त्रुटियों। चलो कुछ मिलता है:

प्रयास # 2

कमान: test 123 "56"

आउटपुट:

START 
a=[123] 
b=["123"] 
c=[123] 
d=[123] 
e=["123"] 
f=[123] 
g=[123 "56"] 
h=["123 "56""] 
i=[123 "56"] 
DONE 

के लिए "सामान्य" तार किसी भी विधि त्रुटियों के बिना काम करता है की तरह लग रहा।

प्रयास # 3

कमान: test ^&-

आउटपुट:

START 
'-' is not recognized as an internal or external command, 
operable program or batch file. 
a=[] 
b=["&-"] 
c=[&-] 
'-' is not recognized as an internal or external command, 
operable program or batch file. 
d=[] 
e=["&-"] 
f=[&-] 
'-' is not recognized as an internal or external command, 
operable program or batch file. 
g=[] 
h=["&-"] 
i=[&-] 
DONE 

आप देख सकते हैं, के मामलों ए, डी और जी में विफल रहा है (=%1, =%~1 और =%*)।

प्रयास # 4

कमान: test "&-"

आउटपुट:

START 
a=["&-"] 
'-""' is not recognized as an internal or external command, 
operable program or batch file. 
b=[""] 
'-""' is not recognized as an internal or external command, 
operable program or batch file. 
c=[] 
'-""' is not recognized as an internal or external command, 
operable program or batch file. 
d=[] 
e=["&-"] 
f=[&-] 
g=["&-"] 
'-""' is not recognized as an internal or external command, 
operable program or batch file. 
h=[""] 
'-""' is not recognized as an internal or external command, 
operable program or batch file. 
i=[] 
DONE 

अब मामलों बी, सी, डी, एच और मैं में विफल रहा है कर रहे हैं (="%1", "=%1", =%~1, ="%*" और "=%*")।

प्रयास # 5

कमान: test ""^&-"

आउटपुट:

START 
'-"' is not recognized as an internal or external command, 
operable program or batch file. 
a=[""] 
b=["""&-""] 
c=[""&-"] 
d=["&-] 
'-"' is not recognized as an internal or external command, 
operable program or batch file. 
e=[""] 
'-"' is not recognized as an internal or external command, 
operable program or batch file. 
f=[] 
'-"' is not recognized as an internal or external command, 
operable program or batch file. 
g=[""] 
h=["""&-""] 
i=[""&-"] 
DONE 

विफल बाकी दो मामलों ई और एफ (="%~1" और "=%~1") एक और जी के साथ (=%1 और %*)।

तो, कोई भी "सेट" संस्करण मेरे कोड को तोड़ने के सभी प्रयासों में भरोसेमंद काम नहीं करेगा!

क्या मुझे अविश्वसनीय स्रोत से आने वाले मौजूदा पैरामीटर पढ़ने के लिए कुछ और दृष्टिकोण याद आ रहा है?

क्या मुझे %… सामान्य चर %…% में मिल सकता है? क्या मैं सीधे " उद्धरण %… में बदल सकता हूं? क्या मैं कुछ विशेष संदर्भ में %* डाल सकता हूं जहां एम्परस & जैसी चीजें निष्पादन में बदलाव नहीं कर सकती हैं? क्या तर्क प्राप्त करने का कोई और तरीका है (सीएमडी को दोबारा कॉल करना, अस्थायी फाइलों का उपयोग करना - कुछ भी?)

मैं ठीक हूं, भले ही यह इन मामलों में मूल स्ट्रिंग को नष्ट कर देगा (अनपेक्षित उद्धरण, अनचाहे स्पेशल इत्यादि), लेकिन मुझे पार्स त्रुटि से छुटकारा पाने की आवश्यकता है (अनियंत्रित कोड निष्पादन का कारण बनता है)!

+0

प्रयास # 5: 'परीक्षण "को बदलने का प्रयास करें"^"-" '' '' '' '' '' - '' '' – aschipfl

उत्तर

5

आप सामान्य प्रतिशत विस्तार के साथ इसे हल नहीं कर सकते!
सबूत:
नमूना तर्क "&"& है।
इस तर्क के साथ बैच फ़ाइल को कॉल करने के लिए, आपको दूसरे एम्पर्सेंड से बचना होगा।

test.bat "&"^& 

सामान्य आदेशों के साथ इसे संभालना संभव नहीं है, क्योंकि आप हमेशा एक निर्विवाद एम्परसंड प्राप्त करते हैं।

set arg=%1 
set "arg=%1" 
set arg=%~1 
set "arg=%~1" 

प्रत्येक पंक्ति एक त्रुटि संदेश के साथ विफल हो जाएगी।

वहाँ किसी भी आदेश है कि %1 या %* साथ असफल नहीं हो है?
हां, REM उन्हें उचित संभाल सकता है।

यह त्रुटियों के बिना काम करता है।

REM %1 

...

अजीब बात है, लेकिन कैसे आप एक REM कथन का उपयोग सामग्री प्राप्त करने से कोई लाभ है?
सबसे पहले आपको यह देखने के लिए ECHO ON सक्षम करना होगा कि यह वास्तव में काम करता है।

echo on 
REM %1 

अच्छा अब आप डिबग आउटपुट

c:\temp>REM "&"&

देख अब आप केवल एक फ़ाइल में डिबग आउटपुट रीडायरेक्ट करना होगा।
ऐसे कई तरीके हैं जो काम नहीं करते हैं।

@echo on 
> arg.txt REM %1 
(REM %1) > arg.txt 
call :func > arg.txt 

.. 
:func 
REM %1 

call redirections itself works, but in the func itself you can't access the% 1 anymore.
But there is one solution to grab the output, with a
FOR` पाश

(
    @echo on 
    for %%a in (42) do (
     rem %1 
    ) 
) > arg.txt 

बेहतर बजाय एक फ़ाइल %1 में तर्क स्टोर करने के लिए है?
हां, क्योंकि फ़ाइल को सामग्री से स्वतंत्र रूप से सुरक्षित तरीके से पढ़ा जा सकता है।

अभी भी कुछ गड़िया छोड़े गए हैं, जैसे /?, ^ या %%a तर्क में।
लेकिन सभी को हल किया जा सकता है।
SO:How to receive even the strangest command line parameters?
SO:Receive multiline arguments

पर और खींचें & के लिए ड्रॉप विषय के बारे में

@echo off 
setlocal DisableDelayedExpansion 
set "prompt=X" 
setlocal DisableExtensions 
(
    @echo on 
    for %%a in (4) do (
     rem #%1# 
    ) 
) > XY.txt 
@echo off 
echo x 
endlocal 
for /F "delims=" %%a in (xy.txt) DO (
    set "param=%%a" 
) 
setlocal EnableDelayedExpansion 
set param=!param:~7,-4! 
echo param='!param!' 

अधिक आप और भी अधिक जटिल समाधान की जरूरत है SO:Drag and drop batch file for multiple files?

संपादित करें: के लिए %*
एक्सटेंशन समाधान अक्षम होना है, अन्य तर्क %a--%~a की तरह संशोधित किया जाएगा।
लेकिन एक्सटेंशन के बिना %* विस्तार अब और काम नहीं करता है।
तो एक्सटेंशन बस %* विस्तार करने के लिए सक्षम हैं, लेकिन FOR से पहले सामग्री एक्सटेंशन अक्षम हो जाएगा पता चलता है।

@echo off 
setlocal EnableExtensions DisableDelayedexpansion 
set "prompt=-" 
(
    setlocal DisableExtensions  
    @echo on 
    for %%a in (%%a) do (
     rem # %*# 
    ) 
) > args.tmp 
@echo off 
endlocal 

set "args=" 
for /F "tokens=1* delims=#" %%G in (args.tmp) DO if not defined args set "args=%%H" 
setlocal EnableDelayedExpansion 
set "args=!args:~1,-4!" 
echo('!args!' 

यह एक सुरक्षित तरीका में सभी तर्कों लाने सकता है, लेकिन एक खींचें & ड्रॉप संचालन से बहस के लिए भी यह पर्याप्त रूप में खिड़कियों एक बग (डिजाइन दोष) नहीं है।
Documents&More जैसी कोई फ़ाइल इस तरह से नहीं लाया जा सकता है।

+0

वाह, प्रसिद्ध जेब! मैंने आपके दृष्टिकोण की कोशिश की और यह काम किया। जब तक मैं '; =, 'जैसे कुछ पास नहीं करता, तब से वे डिलीमीटर होते हैं और अगर अनिश्चित हो तो% 1 पर वितरित नहीं होते हैं। इसके अलावा तर्क (गिनती) प्राप्त करने के लिए यह कठिन है (और उन सभी को निकालें, न केवल पहले)। क्या% * (जो विकलांग एक्सटेंशन के कारण यहां काम नहीं कर रहा है) के साथ कोई समाधान है, जितना संभव हो उतना कम दुष्प्रभाव? मेरे पास अपनी कोशिश है, मैंने इसका परीक्षण किया और कोई ब्रेक नहीं मिला; सभी काम ('/?', '% ~ ...', '^' - परेशानी में और क्या है?)। क्या आप इसे देख सकते हैं? मैं इसे यहां निम्न टिप्पणी में पोस्ट करूंगा: – aleksusklim

+0

'क्योंकि यह मल्टीलाइन है, यहां से प्रतिलिपि बनाने के बाद सभी '#' को नई लाइनों के साथ बदलें। इसमें "बैकस्पेस" वर्ण शामिल है, इसे '$' के साथ प्रतिस्थापित किया गया है - आपको इसे "7 एफएच" चार (Ctrl + बैकस्पेस नोटपैड या Alt + 0127 में) के साथ प्रतिस्थापित करना होगा: '# @ setlocal enableextensions disabledelayedexpansion # @ echo चालू करें और @ (%% $ (_) में (@ कॉल # रिम @% * @ #) के लिए)> tmp.txt&@echo off और endlocal ## सेट करें "! =" और सेट करें "& =" और/f "टोकन = 1 * delims = @ "%% जी में (tmp.txt) सेट करें"! = %% एच "और यदि परिभाषित किया गया है! सेट करें "& = %% एच" #set "और =% और:" = $% "# सेट" & =% और: ~ 1, -2% "# गूंज"% और% "# ~। बैकस्पेस का उपयोग करना परिवर्तनीय विस्तार को रोकता है; उद्धरण-प्रतिस्थापन के रूप में भी उपयोग किया जाता है। – aleksusklim

+0

@aleksusklim यह '% $ -% ~ $' जैसे तर्कों के साथ विफल रहता है, मेरा संपादित उत्तर देखें। मुझे भाग नहीं समझा है _ "एक चर के रूप में बैकस्पेस का उपयोग करना विस्तार को रोकता है "_। – jeb

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