it-swarm-vi.com

Cách thay thế chuỗi bên trong tệp bat bằng chuỗi tham số dòng lệnh

Tôi đã theo dõi trong một tệp bó cmd:

for /f %%l in (%2) do (for %%f in (%%l) do copy "%%f" %1))

lưu ý: tập lệnh này về cơ bản là đọc một tệp văn bản chứa tệp txt được phân cách bằng dấu chấm phẩy có đường dẫn được cho bởi% 2 (ví dụ: chứa c:\test1\file1.cs; d:\file2.js) và sao chép các tệp đến đích thư mục được chỉ định bởi% 1.

Tôi cần thay thế giá trị chuỗi của tham số %1x (cũng được truyền cho tệp bó, ví dụ: %3) bằng giá trị %4 cũng được truyền dưới dạng tham số cho tệp bó.

ví dụ.: 

if %1 = 'test replace x with y'
%3=x
%4=y

vì vậy đầu ra phải là 'kiểm tra thay thế y bằng y'

Làm thế nào tôi có thể đạt được điều này bằng cách sử dụng trình thông dịch lô Windows CMD?

12
DSharper

Trước hết, bạn sẽ phải lưu trữ %1

có nghĩa là: 'thay thế mọi str1 trong variable bằng str2'.

Trong trường hợp của bạn, cả str1str2 đều là tham số, không phải là chuỗi ký tự. Sử dụng trực tiếp mẫu ở trên, bạn có thể kết thúc bằng biểu thức này:

%variable:%3=%4%.

Nhưng điều đó sẽ gây nhầm lẫn cho trình phân tích cú pháp, vì nó sẽ không biết rằng %3%4 nên được đánh giá trước. Trong thực tế, trước tiên, nó sẽ cố gắng đánh giá %variable:% (và không thành công).

Một trong những giải pháp trong trường hợp này có thể là sử dụng một phương pháp gọi là 'lười biếng' đánh giá chậm trễ. Về cơ bản, bạn đang truyền lệnh mà bạn đang đánh giá một biến, cho lệnh CALL. Việc chuyển đổi lệnh gốc thành 'phiên bản GỌI' của nó là như vậy:

ECHO %var% ==> CALL ECHO %%var%%.

Lưu ý gấp đôi %s. Tại thời điểm phân tích, chúng được ước tính thành %s đơn. Lệnh kết quả sẽ được phân tích cú pháp một lần nữa bằng CALL và hiệu ứng cuối cùng sẽ giống như trong trường hợp của lệnh ban đầu, ECHO %var%.

Vì vậy, nó hoạt động giống như lệnh ban đầu (tốt) và cái chúng ta đạt được ở đây là thời gian đánh giá sau này, ý tôi là đánh giá cuối cùng, khi biến thực sự được thay thế bằng giá trị của nó. Biết về hiệu ứng đó, chúng ta có thể xây dựng biểu thức của mình theo cách sao cho %3%4 được đánh giá trước, và sau đó là toàn bộ biểu thức kết quả. Cụ thể, như thế này:

%%variable:%3=%4%%

Sau lần phân tích đầu tiên, biểu thức này sẽ trở thành như thế này:

%variable:x=y%

Điều đó sẽ được phân tích cú pháp một lần nữa và đầu ra sẽ là nội dung được sửa đổi của variable.

Để minh họa rõ hơn, đây là một ví dụ hoạt động đơn giản:

SET "output=%1"
CALL SET output=%%output:%3=%4%%
ECHO %output%

CẬP NHẬT

Có một phương pháp khác để làm điều tương tự, mà có lẽ tôi nên đề cập đầu tiên.

Lệnh Windows Shell hỗ trợ mở rộng thích hợp bị trì hoãn. Nó đơn giản hơn trong sử dụng, nhưng có một số cảnh báo.

Đầu tiên, làm thế nào để sử dụng nó. Cú pháp cho việc mở rộng bị trì hoãn là !var! thay vì %var% để mở rộng ngay lập tức (vẫn còn hiệu lực và có thể được sử dụng cùng với cú pháp mở rộng bị trì hoãn).

Có thể !var! sẽ không hoạt động trong tập lệnh của bạn cho đến khi bạn kích hoạt cú pháp bằng lệnh:

SETLOCAL EnableDelayedExpansion

Lệnh ENDLOCAL đóng khối trong đó cú pháp mở rộng bị trì hoãn là hợp lệ và được diễn giải bởi lệnh Shell.

Kịch bản ví dụ trên có thể được viết lại như thế này:

SET "output=%1"
SETLOCAL EnableDelayedExpansion
SET output=!output:%3=%4!
ECHO !output!
ENDLOCAL

Vậy làm thế nào điều này hoạt động trong trường hợp lệnh SET output=!output:%3=%4!:

  • %3%4 được đánh giá ngay lập tức, tức là tại thời điểm phân tích cú pháp - chúng được thay thế bằng xy tương ứng;

  • lệnh trở thành thế này: SET output=!output:x=y!;

  • lệnh sắp được thực thi - biểu thức ! được ước tính (xs được thay thế bằng ys);

  • lệnh được thực thi - biến output được sửa đổi.

Bây giờ về hãy cẩn thận. Điều đầu tiên cần nhớ là ! trở thành một phần của cú pháp và được sử dụng và diễn giải bất cứ khi nào gặp phải. Vì vậy, bạn sẽ cần phải thoát nó ở nơi bạn muốn sử dụng nó theo nghĩa đen (như ^!).

Một cảnh báo khác là hiệu ứng chính của khối SETLOCAL/ENDLOCAL. Vấn đề là, tất cả các thay đổi đối với các biến môi trường trong một khối như vậy là, tốt, cục bộ. Khi thoát khỏi khối (khi thực hiện ENDLOCAL), biến được đặt thành giá trị mà nó có trước khi nhập nó (trước khi thực hiện SETLOCAL). Điều này có nghĩa đối với bạn rằng giá trị thay đổi của output sẽ chỉ hợp lệ trong khối SETLOCAL mà bạn phải bắt đầu sử dụng mở rộng bị trì hoãn ở vị trí đầu tiên. Có thể điều này có thể không phải là vấn đề trong trường hợp cụ thể của bạn, nếu bạn chỉ cần sửa đổi giá trị và sau đó sử dụng nó ngay lập tức, nhưng có lẽ bạn phải nhớ nó cho tương lai.

Lưu ý: Theo nhận xét của jeb, bạn có thể lưu giá trị đã sửa đổi và rời khỏi khối SETLOCAL bằng thủ thuật này:

ENDLOCAL & SET "output=%output%"

Toán tử & chỉ cần phân định các lệnh khi chúng được đặt trên cùng một dòng. Chúng được thực hiện lần lượt, theo thứ tự chúng được chỉ định. Vấn đề là, tại thời điểm phân tích cú pháp dòng, khối SETLOCAL chưa được để lại, vì vậy %output% ước tính giá trị đã sửa đổi, vẫn còn hiệu lực. Nhưng bài tập thực sự được thực thi sauENDLOCAL, tức là sau khi rời khỏi khối. Vì vậy, bạn đang lưu trữ hiệu quả giá trị được sửa đổi sau khi rời khỏi khối, do đó bảo toàn các thay đổi. (Cảm ơn, jeb!)


Thêm thông tin:

  1. Mở rộng chậm trễ:

  2. Thay thế chuỗi con:

50
Andriy M

Tôi đã thử mã dưới đây trong tệp bó của windows 7:

SET output=%1
CALL SET output=%output:unsigned=signed%
CALL SET output=%output:.apk=-aligned.apk%

Nó hoạt động!

2
Eddie Cheung

Nếu bạn cần thay thế một vài tham số trong một chuỗi, chỉ cần sử dụng "for/f" để đặt biến với thay thế trước đó như sau:

SET "output1=%1"
CALL SET output1=%%output1:%3=%4%%
for /f "tokens=1" %%a in ('echo %output1%') do set output2=%%a
CALL SET output2=%%output2:%5%6%
for /f "tokens=1" %%a in ('echo %output2') do set output3=%%a
0
michael