2010-11-17 27 views
11

như được thảo luận trong một chủ đề khác How to avoid cmd.exe interpreting shell special characters like < > ^ không dễ dàng nhận tất cả thông số từ dòng lệnh.Làm thế nào để nhận được ngay cả các tham số dòng lệnh lạ nhất?

Một đơn giản

set var=%1 
set "var=%~1" 

là không đủ, nếu bạn có một yêu cầu như

myBatch.bat abc"&"^&def 

tôi có một giải pháp, nhưng nó cần một tập tin tạm thời, và nó cũng không phải là chống đạn.

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

Nó không thành công với một cái gì đó giống như myBatch.bat% một, nó hiển thị không phải là % một

trong tình huống này một cách đơn giản echo% 1 sẽ làm việc.
Đó rõ ràng là vòng lặp nhưng tôi không biết cách thay đổi điều này.
Có thể tồn tại một giải pháp đơn giản khác.

Tôi không cần điều này để giải quyết vấn đề thực tế, nhưng tôi thích các giải pháp được chứng minh bằng đạn trong từng trường hợp, không chỉ trong hầu hết các trường hợp.

Trả lời

7

Tôi không nghĩ rằng bất cứ ai tìm thấy bất kỳ lỗ hổng trong này, trừ trường hợp không có khả năng đọc dòng mới trong các thông số:

@echo off 
setlocal enableDelayedExpansion 
set argCnt=1 
:getArgs 
>"%temp%\getArg.txt" <"%temp%\getArg.txt" (
    setlocal disableExtensions 
    set prompt=# 
    echo on 
    for %%a in (%%a) do rem . %1. 
    echo off 
    endlocal 
    set /p "arg%argCnt%=" 
    set /p "arg%argCnt%=" 
    set "arg%argCnt%=!arg%argCnt%:~7,-2!" 
    if defined arg%argCnt% (
    set /a argCnt+=1 
    shift /1 
    goto :getArgs 
) else set /a argCnt-=1 
) 
del "%temp%\getArg.txt" 
set arg 

ở trên xuất phát từ một cuộc thảo luận sôi nổi DosTips - http://www.dostips.com/forum/viewtopic.php?p=13002#p13002. Người dùng DosTips Liviu đã đưa ra phần quan trọng SETLOCAL DisableExtensions.

0

Tùy thuộc vào người dùng nhập lệnh để thoát khỏi bất kỳ ký tự đặc biệt nào. Chương trình của bạn không thể làm bất cứ điều gì về những gì trình bao làm trước khi chương trình của bạn chạy. Không có giải pháp "chống đạn" nào khác cho điều này.

+0

Điểm đó rõ ràng, rõ ràng là abc "&"^& def sẽ được dịch sang abc "&" & def, nhưng vẫn không thể xử lý bằng tập hợp đơn giản "var =% ~ 1" – jeb

+3

Người dùng sau đó sẽ cần phải dự đoán số lần đối số được sử dụng trong tệp lô để thêm mức thoát thích hợp vào nó. Đó không phải là khá khả thi, tôi đoán ;-) – Joey

1

Mã dưới đây dựa trên Foolproof Counting of Arguments chủ đề lan man trên DosTipsthis answer bởi jeb:

@echo off & setLocal enableExtensions disableDelayedExpansion 
(call;) %= sets errorLevel to 0 =% 
:: initialise variables 
set "paramC=0" & set "pFile=%tmp%\param.tmp" 

:loop - the main loop 
:: inc param counter and reset var storing nth param 
set /a paramC+=1 & set "pN=" 

:: ECHO is turned on, %1 is expanded inside REM, GOTO jumps over REM, 
:: and the output is redirected to param file 
for %%A in (%%A) do (
    setLocal disableExtensions 
    set [email protected] 
    echo on 
    for %%B in (%%B) do (
     @goto skip 
     rem # %1 # 
    ) %= for B =% 
    :skip - do not re-use this label 
    @echo off 
    endLocal 
) >"%pFile%" %= for A =% 

:: count lines in param file 
for /f %%A in (' 
    find /c /v "" ^<"%pFile%" 
') do if %%A neq 5 (
    >&2 echo(multiline parameter values not supported & goto die 
) %= if =% 

:: extract and trim param value 
for /f "useBack skip=3 delims=" %%A in ("%pFile%") do (
    if not defined pN set "pN=%%A" 
) %= for /f =% 
set "pN=%pN:~7,-3%" 

:: die if param value is " or "", else trim leading/trailing quotes 
if defined pN (
    setLocal enableDelayedExpansion 
    (call) %= OR emulation =% 
    if !pN!==^" (call;) 
    if !pN!=="" (call;) 
    if errorLevel 1 (
     for /f delims^=^ eol^= %%A in ("!pN!") do (
      endLocal & set "pN=%%~A" 
     ) %= for /f =% 
    ) else (
     >&2 echo(empty parameter values (""^) not supported & goto die 
    ) %= if errorLevel =% 
) else (
:: no more params on cmd line 
    set /a paramC-=1 & goto last 
) %= if defined =% 

:: die if param value contains " 
if not "%pN:"=""%"=="%pN:"=%" (
    >&2 echo(quotes (^"^) in parameter values not supported & goto die 
) %= if =% 

:: assign nth param, shift params, and return to start of loop 
set "param%paramC%=%pN%" & shift /1 & goto loop 

:last - reached end of params 
:: no param values on cmd line 
if %paramC% equ 0 (
    >&2 echo(no parameter values found & goto die 
) %= if =% 
:: list params 
set param 
goto end 

:die 
(call) %= sets errorLevel to 1 =% 
:end 
:: exit with appropriate errorLevel 
endLocal & goto :EOF 

Các điều kiện sau đây sẽ chấm dứt chương trình ngay lập tức:

  • không có thông số tìm thấy
  • multiline tham số
  • thông số trống (.210, hoặc " được phép cho tham số cuối cùng)
  • một hoặc nhiều dấu ngoặc kép (") trong một giá trị tham số

Để giảm bớt những hạn chế này, chỉ đơn giản là nhận xét ra các dòng có liên quan. Đọc các bình luận nội tuyến để biết thêm thông tin. Không tìm cách tắt bẫy thông số nhiều dòng!

Các vấn đề liên quan