2013-06-26 31 views
8

Tôi hiểu rằng đường ống PowerShell hoạt động bằng cách lấy đầu ra của một lệnh ghép ngắn và chuyển nó tới lệnh ghép ngắn khác làm đầu vào. Nhưng làm thế nào nó đi về việc này?Khái niệm Pipeline Pipeline hoạt động như thế nào?

Lệnh ghép ngắn đầu tiên có kết thúc và sau đó chuyển tất cả các biến đầu ra cùng một lúc, sau đó được xử lý bởi lệnh ghép ngắn tiếp theo?

Hoặc là mỗi đầu ra từ lệnh ghép ngắn đầu tiên được lấy một lần và sau đó chạy nó qua tất cả các lệnh ghép ngắn còn lại của đường ống?

Trả lời

10

Bạn có thể xem làm thế nào để đường ống làm việc với một chút đơn giản của kịch bản:

function a {begin {Write-Host 'begin a'} process {Write-Host "process a: $_"; $_} end {Write-Host 'end a'}} 
function b {begin {Write-Host 'begin b'} process {Write-Host "process b: $_"; $_} end {Write-Host 'end b'}} 
function c { Write-Host 'c' } 

1..3 | a | b | c 

Đầu ra:

begin a 
begin b 
process a: 1 
process b: 1 
process a: 2 
process b: 2 
process a: 3 
process b: 3 
end a 
end b 
c 
5

Ống Powershell hoạt động theo cách không đồng bộ. Có nghĩa là đầu ra của lệnh ghép ngắn đầu tiên có sẵn cho lệnh ghép ngắn thứ hai ngay lập tức một đối tượng tại thời điểm đó (ngay cả khi lệnh đầu tiên chưa hoàn tất thực thi).

Ví dụ, nếu bạn chạy các dòng dưới đây:

dir -recurse| out-file C:\a.txt 

và sau đó dừng thực hiện bằng cách nhấn Control + C bạn sẽ thấy một phần của thư mục được ghi vào tập tin văn bản.

Một ví dụ tốt hơn là đoạn mã sau: (đó là thực sự hữu ích để xóa tất cả các tập tin .tmp trên ổ c :)

get-childitem c:\ -include *.tmp -recurse | foreach ($_) {remove-item $_.fullname} 

Mỗi lần $ _ trong cmdlet thứ hai được giá trị của một (đơn tập tin)

1

Cả hai câu trả lời đều có thể cung cấp cho bạn một số thông tin tốt về pipelining. Tuy nhiên, có nhiều điều để nói.

Trước tiên, để trực tiếp giải quyết câu hỏi của bạn, bạn đã đặt ra hai cách có thể mà đường ống có thể hoạt động. Và cả hai đều đúng ... tùy thuộc vào các lệnh ghép ngắn ở hai bên của đường ống! Tuy nhiên, cách đường ống dẫn nên hoạt động gần với quan niệm thứ hai của bạn: các đối tượng được xử lý từng lần một. (Mặc dù không có gì đảm bảo rằng một đối tượng sẽ đi qua trước khi bước tiếp theo được bắt đầu vì mỗi thành phần trong đường ống là không đồng bộ, như S Nash đã đề cập.)

Vì vậy, tôi có ý gì? cmdlets "? Nếu bạn đang nói về lệnh ghép ngắn được cung cấp bởi Microsoft, chúng có khả năng hoạt động như bạn mong đợi, truyền qua từng đối tượng thông qua đường ống một cách hiệu quả nhất có thể. Nhưng nếu bạn đang nói về các lệnh ghép ngắn mà bạn viết, nó phụ thuộc vào cách bạn viết chúng: nó cũng dễ dàng để viết các lệnh ghép ngắn mà không thực hiện đúng pipelining như những đường dẫn thành công!

Có hai chế độ nguyên tắc thất bại:

  • tạo ra tất cả các đầu ra trước khi phát ra bất kỳ vào đường ống, hoặc
  • thu thập tất cả đầu vào đường ống trước khi xử lý bất kỳ.

Điều bạn muốn phấn đấu, tất nhiên, là xử lý từng đầu vào ngay khi nhận được và phát ra đầu vào ngay sau khi được xác định.Để biết ví dụ chi tiết về tất cả những điều này, hãy xem bài viết của tôi, Ins and Outs of the PowerShell Pipeline, chỉ được xuất bản trên Simple-Talk.com.