2012-02-20 23 views
30

Trong tệp batch của tôi trên Windows XP, tôi muốn sử dụng %* để mở rộng đến tất cả các tham số ngoại trừ đầu tiên. tập tin
thử nghiệm (foo.bat):Cách làm cho SHIFT hoạt động với% * trong các tệp hàng loạt

@echo off 
echo %* 
shift 
echo %* 

Gọi:

C:\> foo a b c d e f 

thực tế kết quả:

a b c d e f 
a b c d e f 

mong muốn kết quả:

a b c d e f 
b c d e f 

Làm cách nào để đạt được kết quả mong muốn? Cảm ơn!!

Trả lời

17

Sẽ không tuyệt vời nếu CMD.EXE hoạt động theo cách đó! Thật không may là không có một cú pháp tốt mà sẽ làm những gì bạn muốn. Điều tốt nhất bạn có thể làm là phân tích cú pháp dòng lệnh và xây dựng một danh sách đối số mới.

Thứ gì đó như thế này có thể hoạt động.

@echo off 
setlocal 
echo %* 
shift 
set "args=" 
:parse 
if "%~1" neq "" (
    set args=%args% %1 
    shift 
    goto :parse 
) 
if defined args set args=%args:~1% 
echo(%args% 

Nhưng trên có vấn đề nếu một cuộc tranh cãi chứa các ký tự đặc biệt như ^, &, >, <, | được thoát thay vì trích dẫn.

Xử lý đối số là một trong nhiều khía cạnh yếu của lập trình bó Windows. Đối với mọi giải pháp, có tồn tại một ngoại lệ gây ra vấn đề.

3

Đừng nghĩ rằng có một cách đơn giản để làm như vậy. Bạn có thể thử chơi với các workaround sau đây thay vì:

@ECHO OFF 
>tmp ECHO(%* 
SET /P t=<tmp 
SETLOCAL EnableDelayedExpansion 
IF DEFINED t SET "t=!t:%1 =!" 
ECHO(!t! 

Ví dụ:

test.bat 1 2 3=4 

Output:

2 3=4 
+0

Tôi không thấy lợi ích của các tập tin tạm thời - 'đặt t =% *' sẽ chỉ làm việc tốt. Câu trả lời này sẽ thất bại nếu% 1 chứa '=' hoặc bắt đầu bằng '*' hoặc '~'. Cũng sẽ có vấn đề nếu arg được phân tách bằng ',' hoặc ';' thay vì dấu cách. Tốt hơn là chỉ xóa% 1 và để (các) dấu phân tách tại chỗ. – dbenham

+0

Vấn đề kẻ giết người - câu trả lời này sẽ trả lời sai nếu arg là 'A A B'. Có thể được cải thiện với 'set t =! T: *% 1 =!' – dbenham

+0

Sử dụng 'set" t =! T: *% 1 =! 'Sửa đổi, câu trả lời này sẽ vẫn thất bại nếu% 1 chứa' = ', nhưng bắt đầu với '*' hoặc '~' là ok – dbenham

2

That's dễ dàng:

setlocal ENABLEDELAYEDEXPANSION 
    set "_args=%*" 
    set "_args=!_args:*%1 =!" 

    echo/%_args% 
endlocal 

Cùng một điều với c omments:

:: Enable use of ! operator for variables (! works as % after % has been processed) 
setlocal ENABLEDELAYEDEXPANSION 
    set "_args=%*" 
    :: Remove %1 from %* 
    set "_args=!_args:*%1 =!" 
    :: The %_args% must be used here, before 'endlocal', as it is a local variable 
    echo/%_args% 
endlocal 

Ví dụ:

lets say %* is "1 2 3 4": 

setlocal ENABLEDELAYEDEXPANSION 
    set "_args=%*"    --> _args=1 2 3 4 
    set "_args=!_args:*%1=!" --> _args=2 3 4 

    echo/%_args% 
endlocal 

Ghi chú:

  • Không làm việc nếu có tranh cãi chứa!hoặc & char
  • Bất kỳ những khoảng trắng trong lập luận sẽ KHÔNG được gỡ bỏ
+0

Bạn cần xóa đối số% 1, không phải% 0 (là tên của tập lệnh) –

+0

Thật vậy, bạn chính xác. Tôi đã chỉnh sửa% 0 thành% 1 ngay bây giờ. Cảm ơn. – cyberponk

+2

Như được viết, điều này là nguy hiểm sai, bởi vì giá trị cho arg đầu tiên có thể được lặp đi lặp lại trong một arg tiếp theo, và mã của bạn sẽ loại bỏ cả hai. Điều đó có thể được sửa bằng cách sử dụng '*' để loại bỏ mọi thứ thông qua cá thể đầu tiên: 'set _args =! _ Args: *% 1 =!'. Các vấn đề khác không thể sửa được là nó sẽ thất bại nếu '% 1' chứa'! 'Hoặc' = '. – dbenham

0

Một cách dễ dàng để làm điều này là:

set "_args=%*" 
set "_args=%_args:* =%" 

echo/%_args% 

Ghi chú:

  • Không hoạt động nếu đối số đầu tiên (% 1) được 'trích dẫn' hoặc "được trích dẫn kép"
  • Không hoạt động nếu bất kỳ tranh cãi chứa & char
  • Bất kỳ những khoảng trắng trong lập luận sẽ KHÔNG được gỡ bỏ
1

tôi phải làm điều này thời gian gần đây và đến với điều này:

setlocal EnableDelayedExpansion 

rem Number of arguments to skip 
set skip=1 

for %%a in (%*) do (
    if not !position! lss !skip! (
    echo Argument: '%%a' 
) else (
    set /a "position=!position!+1" 
) 
) 

endlocal 

Nó sử dụng vòng lặp để bỏ qua hơn N đối số đầu tiên. Có thể được sử dụng để thực hiện một số lệnh cho mỗi đối số hoặc tạo danh sách đối số mới:

setlocal EnableDelayedExpansion 

rem Number of arguments to skip 
set skip=1 

for %%a in (%*) do (
    if not !position! lss !skip! (
    set args=!args! %%a 
) else (
    set /a "position=!position!+1" 
) 
) 

echo %args% 

endlocal 

Xin lưu ý rằng mã ở trên sẽ thêm không gian hàng đầu vào đối số mới. Nó có thể được gỡ bỏ như thế này:

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