2010-04-02 35 views
5

Tôi cố gắng để đọc một số thông tin từ một tập tin văn bản bằng cách sử dụng cửa sổ dòng lệnh, và lưu nó vào một biến giống như "thiết lập thông tin = 1234"DOS lệnh batch để đọc một số thông tin từ tập tin văn bản

Dưới đây là nội dung của tệp txt, thực ra tôi chỉ cần số sửa đổi và vị trí của nó luôn là cùng một dòng 5 và từ cột 11 đến 15. Trong mẫu là 1234 và tôi tự hỏi có cách nào để lưu không nó vào một biến trong dòng lệnh Dos.

Cảm ơn rất nhiều!

svninfo.txt:

Path: . 
URL: https://www.abc.com 
Repository Root: https://www.abc.com/svn 
Repository UUID: 12345678-8b61-fa43-97dc-123456789 
Revision: 1234 
Node Kind: directory 
Schedule: normal 
Last Changed Author: abc 
Last Changed Rev: 1234 
Last Changed Date: 2010-04-01 18:19:54 -0700 (Thu, 01 Apr 2010) 

Trả lời

11

Dưới đây là một phiên bản một dòng:

for /f "tokens=2" %%i in ('findstr Revision: input.txt') do set revision=%%i 
  1. findstr được sử dụng để f ilter tập tin. Nó sẽ in "input.txt: Revision: 1234"
  2. Sau đó, "tokens = 2" có nghĩa là chúng tôi quan tâm đến mã thông báo thứ hai, "1234". Theo mặc định cho các khoảng ngắt trên khoảng trắng.
+0

Rất thông minh! Tôi đã quên về findstr. –

+0

Để thêm vào điều này: Bạn có lẽ nên sử dụng kết hợp cụm từ thông dụng và neo chuỗi 'Revision:' vào đầu dòng. Bạn sẽ không bao giờ biết liệu nó có thể không xuất hiện ở những nơi khác nữa không :-) – Joey

+0

@Johannes muốn bạn sử dụng 'fidnstr/R' để bật regex. –

4

Đoạn mã sau đây cho thấy làm thế nào để làm điều này:

@echo off 
setlocal enableextensions enabledelayedexpansion 
set revision= 
for /f "delims=" %%a in (input.txt) do (
    set line=%%a 
    if "x!line:~0,10!"=="xRevision: " (
     set revision=!line:~10! 
    ) 
) 
echo !revision! 
endlocal 

đầu ra của nó là 1234 như mong muốn.

setlocal là những gì tôi sử dụng trong mọi tập lệnh để đảm bảo các biến được xử lý theo cách đã biết. Câu lệnh for xử lý từng dòng trong tệp đầu vào (bit delims ngăn dòng được mã hóa thành các từ riêng biệt).

Các bit !line:~ là các đoạn có !line:~0,10! là mười ký tự đầu tiên và !line:~10! là phần còn lại. Vì vậy, về cơ bản, nó kiểm tra tất cả các dòng để xem nó bắt đầu với "Revision: " và, nếu có, trích xuất phần còn lại của dòng để sau này.

+0

Cảm ơn rất nhiều! Nó hoạt động. – Ray

+0

Cá nhân tôi đã đi với biến thể 'findstr'. Làm cho ý định rõ ràng hơn nhiều và ngắn hơn một chút vì bạn không phải kiểm tra sự bắt đầu của dòng với các chất nền. – Joey

+0

Đã lâu rồi, nhưng IIRC tôi thích đặt '@ SETLOCAL' vào dòng đầu tiên, vì vậy' @ECHO OFF' không ảnh hưởng đến cài đặt echo của một tập lệnh gọi. Ngoài ra, tôi muốn thay thế '@ECHO OFF' bằng' @IF NOT DEFINED _ECHO ECHO OFF', vì vậy tôi có thể sử dụng 'SET _ECHO = 1' để gỡ lỗi các tập lệnh của tôi. –

2

Sử dụng lệnh for để phân tích các tập tin:

for /f "skip=4 tokens=2" %%l in (svninfo.txt) do (
    set revision=%%l 
    goto gotrev 
) 

:gotrev 
echo revision is %revision% 
+0

Khá succint này! :) –

+0

gọn gàng, có, nhưng phiên bản của paxdiablo có lẽ là một lựa chọn tốt hơn, vì nó thực sự kiểm tra dữ liệu nó sẽ trả lại cho sự phù hợp thay vì chỉ dựa vào một số dòng. –

1

nếu bạn có thể sử dụng các công cụ GNU, chẳng hạn như gawk

@echo off 
for /F %%a in ('gawk -F":" "$1~/Revision/{print $2}" file') do (
     set var=%%a 
) 
echo %var% 
1

Biết cách sử dụng kịch bản lệnh khéo léo là tuyệt vời, nhưng việc sử dụng PowerShell thậm chí còn tốt hơn. Dưới đây là một cách để thực hiện:

$revision = ((gc .\svninfo.txt | ? { $_.StartsWith('Revision: ') }) -split ' ')[1] 

Điều gì đang xảy ra?

$revision là một biến

gcGet-Content, aka type. Mỗi dòng trong tập tin sẽ trở thành một chuỗi trong một chuỗi (đường ống).

?Where-Object. Nó lọc các đối tượng trong một đường ống dựa trên một điều kiện.

{} delimits một khối kịch bản

$_ là đối tượng hiện hành trong các đường ống.

-split gọi String.Split() trong .NET, đem lại cho bạn một mảng của các đối tượng

[1] chỉ số trong mảng để

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