2009-09-14 29 views
41

Trên Linux, tôi có thể làm:Powershell: Thiết lập một biến môi trường cho một lệnh duy nhất mà thôi

$ FOO=BAR ./myscript 

gọi là "myscript" với các biến môi trường FOO đang được thiết lập.

Có điều gì đó tương tự có thể xảy ra trong Powershell, tức là không phải đặt biến đầu tiên, hãy gọi lệnh và sau đó không đặt lại biến đó?

Để rõ ràng hơn về trường hợp sử dụng của tôi - Tôi không muốn sử dụng điều này như là một phần của tập lệnh. Thay vào đó, tôi có một kịch bản của bên thứ ba có hành vi mà tôi có thể kiểm soát bằng cách sử dụng các biến môi trường, nhưng trong trường hợp này, không phải là các đối số dòng lệnh. Vì vậy, có khả năng luân phiên giữa gõ

$ OPTION=1 ./myscript 

$ ./myscript 

sẽ chỉ được rất tiện dụng.

+0

Tôi đoán câu hỏi của tôi sẽ là lý do tại sao bạn sẽ cần phải làm điều này? Tôi nghĩ rằng có một giải pháp tốt hơn. – EBGreen

+6

Đó thường không phải là một câu hỏi hữu ích, @EBGreen. Thực tế là khả năng có trong vỏ UNIX cho thấy rằng có một sử dụng cho nó. Tắt đầu của tôi: kiểm soát tên người dùng và địa chỉ email mà git sử dụng cho các cam kết. Không có tùy chọn dòng lệnh cho những người - bạn phải đặt chúng trong ~/.gitconfig, .git/config trong mỗi kho lưu trữ, hoặc envars. Trong số các tùy chọn này, envars rõ ràng là dễ dàng hơn để thiết lập on-the-fly (và thuận tiện ghi đè các giá trị trong các tập tin). Vì vậy, nếu tôi muốn thay đổi tên tác giả của tôi cho một "git commit" trong PowerShell, làm thế nào để làm điều đó? –

Trả lời

-3

Bạn có thể phạm vi biến cho hàm và tập lệnh.

$script:foo = "foo" 
$foo 
$function:functionVariable = "v" 
$functionVariable 

Biến mới cũng có thông số -scope nếu bạn muốn chính thức và khai báo biến bằng biến mới.

+0

Hmmm ... Đừng nghĩ câu trả lời này được áp dụng ở đây. Biến PowerShell không phải là biến môi trường. Dựa trên câu hỏi, người hỏi không sử dụng biến môi trường như không gian đầu (giống như trong CMD [nếu trường hợp đó xảy ra, câu trả lời này sẽ áp dụng]), nhưng cần thao tác môi trường trước khi gọi ra lệnh bên ngoài và sau đó khôi phục môi trường sau đó (hoặc một cái gì đó để có hiệu lực đó). – chwarr

16

Nói chung sẽ tốt hơn khi chuyển thông tin tới tập lệnh thông qua tham số thay vì một biến số toàn cầu là . Nhưng nếu đó là những gì bạn cần làm và bạn muốn tự động dọn dẹp biến sau đó giới thiệu một phạm vi mới như vậy:

& { $foo = 'bar'; $env:foo = 'bar'; ./myscript } 

Một vài điều cần lưu ý về điều này. Đầu tiên, khi phạm vi (scriptblock) được thoát, $ foo không còn tồn tại nữa. Nó chỉ tồn tại trong bối cảnh của scriptblock. Tuy nhiên biến môi trường $ env: foo vẫn tồn tại vì đó thực sự là một thay đổi toàn cầu. Bạn có thể xóa biến đó như vậy:

Remove-Item Env:\foo 
+1

Chỉ là một suy nghĩ: Bạn không thể chỉ sinh ra một quy trình PowerShell mới, đưa scriptblock vào nó thông qua tham số -Command? Bằng cách đó bạn không phải làm sạch môi trường sau đó, vì nó sẽ được chứa trong quá trình con. Mặc dù tôi đang nói chuyện với một MVP PowerShell vì vậy điều này có thể không hoạt động :-) – Joey

+2

Keith, chúng tôi có một push-environmentblock và pop-environmentblock trong Pscx cho chính xác kịch bản này ;-) – x0n

+2

Johannes, điều đó sẽ hoạt động tốt nhưng bằng cách nào đó có vẻ như gian lận. :-) PSCX Push/Pop-EnvironmentBlock (một * I * thay đổi để thực hiện công việc theo cách này) sẽ hoạt động nhưng nó không có hỗ trợ dọn dẹp tự động mà một scriptblock có. –

2

Để thực hiện cú pháp Unix, bạn không chỉ phải đặt biến môi trường, mà phải đặt lại giá trị cũ sau khi thực hiện lệnh. Tôi đã thực hiện điều này cho các lệnh phổ biến mà tôi sử dụng bằng cách thêm các hàm tương tự như sau vào hồ sơ PowerShell của tôi.

function cmd_special() 
{ 
    $orig_master=$env:app_master 
    $env:app_master='http://host.example.com' 
    mycmd $args 
    $env:app_master=$orig_master 
} 

Vì vậy mycmd là một số thực thi mà hoạt động khác nhau tùy thuộc vào giá trị của biến môi trường app_master. Bằng cách xác định cmd_special, bây giờ tôi có thể thực hiện cmd_special từ dòng lệnh (bao gồm các tham số khác) với bộ biến môi trường app_master ... và nó được đặt lại (hoặc thậm chí không được đặt) sau khi thực hiện lệnh.

Có lẽ, bạn cũng có thể thực hiện điều này đặc biệt cho một lời gọi đơn lẻ.

& { $orig_master=$env:appmaster; $env:app_master='http://host.example.com'; mycmd $args; $env:app_master=$orig_master } 

Nó thực sự phải dễ hơn thế này, nhưng rõ ràng đây không phải là trường hợp sử dụng được hỗ trợ bởi PowerShell. Có thể một phiên bản tương lai (hoặc chức năng của bên thứ ba) sẽ tạo thuận lợi cho trường hợp sử dụng này. Sẽ tốt hơn nếu Powershell có một lệnh nhỏ để làm điều này, ví dụ::

with-env app_master='http://host.example.com' mycmd 

Có thể một giáo sư Powershell có thể đề xuất cách người ta có thể viết một lệnh ghép ngắn như vậy.

0

tôi đã thúc đẩy đủ về vấn đề này mà tôi đã đi trước và đã viết một kịch bản cho nó: with-env.ps1

Cách sử dụng:

with-env.ps1 FOO=foo BAR=bar your command here 

# Supports dot-env files as well 
with-env.ps1 .\.env OTHER_ENV=env command here 

Mặt khác, nếu bạn cài đặt Gow bạn có thể sử dụng env.exe mà có thể mạnh hơn một chút so với kịch bản nhanh mà tôi đã viết ở trên.

Cách sử dụng:

env.exe FOO=foo BAR=bar your command here 

# To use it with dot-env files 
env.exe $(cat .env | grep.exe -v '^#') SOME_OTHER_ENV=val your command 
Các vấn đề liên quan