Mẹo chơi gôn trong PowerShell


45

Bạn có mẹo chung nào để chơi golf trong Windows PowerShell? Tôi đang tìm kiếm những ý tưởng có thể được áp dụng cho các vấn đề về mã golf nói chung ít nhất là cụ thể đối với PowerShell (ví dụ: "xóa bình luận" không phải là một câu trả lời). Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời.

Cách thức gần như nguyên văn từ câu hỏi của marcog .


3
Khi tôi googled "PowerShell golf", đây là lần đầu tiên!
Matt

Câu trả lời:


24

Quyền hạn của 10 chữ với ký hiệu khoa học:

4e6 = 4000000

Quyền hạn của 2 chữ:

4KB = 4096
4MB = 4194304
4GB = 4294967296

# TB and PB suffixes also exist, but less useful for golf.

Có thể có ích.


19

Nếu bạn cần chạy một vòng lặp và bạn biết chính xác số lần cần chạy mỗi lần, hãy xem xét việc đưa một mảng các số nguyên liền kề vào ForEach-Objectthông qua %bí danh thay vì sử dụng for.

for($x=1;$x-le10;$x++){...}

đấu với

1..10|%{...}


18

Bạn có thể bỏ qua khoảng trắng rất nhiều trong PowerShell. Nếu cảm thấy có thể không cần thiết, thì hoàn toàn không thể. Điều này đặc biệt hữu ích trong so sánh.

Thí dụ:

$x-eq$i-and$x-ne9

so với

$x -eq $i -and $x -ne 9

Nếu bạn cần phân nhánh tập lệnh của mình dựa trên kết quả của một thử nghiệm duy nhất có thể có nhiều kết quả, switchđôi khi có thể khớp hoặc đánh bại một câu lệnh if.

Ví dụ (chuyển đổi so với if / other - tie):

if($x%2-eq0){'even'}else{'odd'}

so với

switch($x%2){0{'even'}1{'odd'}}

Hoặc (chuyển đổi so với if / otherif / other - chuyển đổi thắng 15):

if($x%2-eq0){'even'}elseif($x%2-eq1){'odd'}else{'error'}

so với

switch($x%2){0{'even'}1{'odd'}2{'error'}}

Nếu công tắc thực sự dựa trên các kết quả toán học nhất định, như thao tác modulo ở trên, bạn có thể thay thế hoàn toàn công tắc bằng một mảng. Ở đây, nó lưu 13 ký tự khác và thậm chí còn ngắn hơn câu lệnh if / other ban đầu. (Cảm ơn Danko Durbic vì điều này.)

('even','odd','error')[$x%2]

Nếu bạn sẽ sử dụng một lệnh cụ thể rất nhiều, đặc biệt là một lệnh không có bí danh tay ngắn có sẵn, hãy thiết lập bí danh một ký tự từ sớm.

Thí dụ:

nal g Get-Random;g 10;g 10;g 10

so với

Get-Random 10;Get-Random 10;Get-Random 10

('even','odd')[$x%2]FYI.
TheIncorritable1

15

Đóng gói lệnh xác định một biến trong ngoặc đơn cho phép bạn cung cấp định nghĩa của biến trực tiếp cho các lệnh khác.

Ví dụ: bạn có thể đặt $ x và sau đó đặt $ y dựa trên giá trị của $ x trong một lần chụp với điều này:

$y=($x=1)+1

Thay vì điều này:

$x=1;$y=$x+1

Bạn có thể đặt $ h và xuất nó với điều này:

($h='Hello World!')

Thay vì điều này:

$h='Hello World!';$h

1
Điều này đặc biệt hữu ích để gọi các phương thức trên các đối tượng. ($x=New-Object Windows.Forms.Form).Controls.Add($t)
SpellingD

14

Một chuyển đổi có thể hoạt động như một vòng lặp, khi được đưa ra một mảng. Ví dụ:

$FooBarMeh='a','b','c'
switch ($FooBarMeh)
{
    'a'{'FOO'}
    'b'{'BAR'}
    default{'MEH'}
}

Sẽ xuất:

FOO
BAR
MEH

Tôi không hoàn toàn chắc chắn nơi này sẽ hữu ích, nhưng tôi hy vọng nó sẽ có ích cho ai đó một thời gian.


2
Nó rất hữu ích mỗi khi bạn cần ForEach-Objectswitchtrong đó. Ví dụ, mã (trong thế giới thực) rất đẹp để viết các trình phân tích cú pháp nhanh các tệp văn bản nơi bạn cần thực hiện các thao tác khác nhau tùy thuộc vào biểu thức nào phù hợp với dòng.
Joey

Điều này thật ... kỳ lạ. Một mảng không nên phù hợp với char, nhưng nó có.
con mèo

@Joey Đó là những gì switch -File $pathdành cho
TheIncorritable1 16/11/18

Không phải tất cả mọi thứ được phân tích cú pháp đều là một tập tin.
Joey

12

Thay thế [math]::powbằng phép nhân. Thay vì

[math]::pow($a,$b)

bạn có thể viết

"$a*"*$b+1|iex

Điều này hoạt động cho số mũ số nguyên> = 0.


Tôi cần xem câu trả lời này để hiểu iex... Bí danh choInvoke-Expression
HeatfanJohn

11

Toán tử so sánh hoạt động trên các bộ sưu tập các giá trị bằng cách trả về các giá trị khớp:

1..5 -gt 2

sẽ mang lại 3, 45. Trong một số trường hợp, điều này có thể giúp tiết kiệm lâu hơn |?{$_...}.

-match là một toán tử so sánh quá.


1
Lưu ý rằng bạn không cần khoảng trắng trong ví dụ đó1..5-gt2
Matt

1
Tôi biết; đây là nhiều hơn về việc thể hiện kỹ thuật. Không gian là trong một câu trả lời riêng biệt .
Joey

11

Sử dụng bí danh bất cứ khi nào có thể. Có một loạt những cái hữu ích:

?        Where-Object
%        ForEach-Object
gu       Get-Unique
sort     Sort-Object
iex      Invoke-Expression

11

Bạn muốn tìm tối đa hoặc tối thiểu của một bộ sưu tập các giá trị? Đã thử

(...|measure -ma).Maximum

hoặc là

(...|measure -mi).Minimum

đã sẵn sàng?

Chỉ cần sắp xếp và sử dụng mục cuối cùng hoặc đầu tiên:

(...|sort)[-1]  # maximum
(...|sort)[0]   # minimum

1
Và, nếu bạn biết độ dài của bộ sưu tập các giá trị và nó nhỏ hơn 10 ...
wizzwizz4

@ wizzwizz4: Ồ, độ dài tối đa thường có thể được sử dụng một cách sáng tạo, không nhất thiết phải là 10. Mặc dù trong trường hợp cụ thể này, tôi không nhớ lại một trường hợp mà nó từng giúp.
Joey

1
Ý tôi là, nếu mục cuối cùng được biết đến là 0, 1, 2, 3, 4, 5, 6, 7, 8hay 9, nó sẽ tiết kiệm một byte để viết dài được biết thay vì -1.
wizzwizz4

10

Rút ngắn tên tài sản

Đáng buồn thay, không giống như các tham số, các thuộc tính / phương thức (bất cứ thứ gì được truy cập bằng dấu chấm .) thường không thể được rút ngắn xuống dạng không rõ ràng của nó.

Nhưng một số lệnh ghép ngắn nhất định có thể hoạt động trên tên thuộc tính và lấy ký tự đại diện, và có các bộ tham số ít được biết đến %?có thể hữu ích.

Thông thường chúng ta chuyển qua một scriptblock và tham chiếu đến mục này $_, nhưng có một dạng khác trong số này có tên thuộc tính và nó chấp nhận ký tự đại diện.

$o|select Le*  
$o|%{$_.Length}

Với một thuộc tính như .Lengthchúng ta không thể sử dụng phép thuật v3 thường hoạt động trên một mảng vì đó Lengthlà một thuộc tính của chính mảng đó, vì vậy hai thuộc tính trên có thể được sử dụng để lấy độ dài của từng thành viên. Đi selectkèm trong một chút ngắn hơn.

Nhưng %có thể lấy tên tài sản trực tiếp và trả về giá trị đó:

$a|% Length

Mà có thể được rút ngắn với ký tự đại diện. Ký tự đại diện phải giải quyết thành một thuộc tính (hoặc phương thức, nhiều hơn về sau), vì vậy nó sẽ gây ra lỗi hữu ích nếu không, cho biết chính xác thành viên nào có thể giải quyết.

Trong trường hợp Length, Le*thường là ngắn nhất. Ngay cả trên một chuỗi, phương thức này ngắn hơn 1 byte so với chỉ sử dụng thuộc tính.

$a.Length                # 9   #(doesn't work on array)
$a|%{$_.Length}          # 15
$a|% Le*                 # 8

Nhưng tùy thuộc vào những gì bạn đang làm với điều này, điều này có thể tồi tệ hơn. Bạn có thể làm $a.Length*5nhưng để làm điều đó với biểu thức đường ống bạn phải bọc nó ($a|% Le*)*5; có thể vẫn còn giá trị nếu nó chống lại một mảng, nhưng vấn đề là nó không phải lúc nào cũng thích hợp như một sự thay thế thẳng.

Nó cũng hoạt động với các phương thức và bạn có thể bỏ qua cái ()mà làm cho một tên đầy đủ có cùng độ dài, nhưng hạn chế tương tự như trên về việc đôi khi phải bọc nó. Phương thức phải có quá tải không có tham số (bạn có thể truyền đối số bằng cách đặt chúng sau tên phương thức, điều này thực sự tốt):

$a.ToUpper()             # 12
$a|% *per                #  9

Với các đối số:

'gaga'-replace'g','r'    # 21
'gaga'|% *ce g r         # 16

Chúng không hoàn toàn giống nhau ở chỗ -replacetoán tử thực hiện thay thế regex, nhưng nếu bạn chỉ thực hiện thay thế chuỗi, thì có thể (bây giờ) ngắn hơn để sử dụng phương thức; nó giúp các chuỗi là các đối số cmdlet thay vì các đối số phương thức để chúng không cần được trích dẫn.

Thuộc tính đối tượng

?cũng có thể lấy (một phần) tên thuộc tính và áp dụng "toán tử" cho nó (dưới dạng tham số chuyển đổi). Một lần nữa, điều này có thể ngắn hơn so với sử dụng cách Where-Objecttiếp cận scriptblock tiêu chuẩn nếu tên thuộc tính đủ dài và duy nhất.

$a|?{$_.Length-gt5}      # 19
$a|? Le* -GT 5           # 14

($a|% Le*)-gt5           # 14 - Lengths, not objs

1
Một trong số ít nơi yêu cầu khoảng trắng. Đẹp tìm, mặc dù. Tôi có thể nghĩ về một số lĩnh vực mà điều này sẽ rút ngắn mọi thứ.
admBorkBork

Joey chỉnh sửa tốt đẹp! Cảm ơn.
nghĩa tự do

Tìm cho bạn một cách để làm cho nó ngắn hơn ;-) ... điều đáng buồn ở đây là toàn bộ nó lại là một đường ống dẫn, điều này hạn chế tính hữu dụng của nó một chút. Hay đúng hơn, có rất nhiều nơi bạn phải bọc nó lại trong ngoặc đơn để có được biểu thức. Nhưng rất ít kỹ thuật chơi gôn không có sự đánh đổi ...
Joey

1
@ConnorLSW ah vâng tôi có ý định cập nhật điều này vì tôi nhận ra rằng bạn có thể vượt qua các cuộc tranh luận theo cách đó, điều này làm tăng đáng kể tính hữu dụng của nó. Công dụng tuyệt vời của .ToString()!
briantist

2
@briantist điều này đã biến PowerShell thành một ngôn ngữ cạnh tranh hơn nhiều, thực sự cắt bỏ một số cuộc gọi .Net khó chịu.
colsw

9

Tìm một tổng số đường dài:

(...|measure -s).Sum

Một cách ngắn hơn:

...|%{$s+=$_};$s

Và thậm chí ngắn hơn:

...-join'+'|iex

9

Dấu chấm phẩy và ngắt dòng có thể hoán đổi cho nhau. Mã golf thường dễ đọc hơn nếu không bị kẹt vào một dòng. Và độ dài vẫn như nhau (miễn là bạn sử dụng U + 000A làm ngắt dòng mà PowerShell xử lý mà không gặp sự cố).


2
Đợi đã, chúng tôi lo lắng về khả năng đọc?!
Kevin Cox

4
Nếu nó không có ảnh hưởng đến chiều dài ... tại sao không?
Joey

Về mặt kỹ thuật, nó không tạo ra sự khác biệt vì dấu chấm phẩy là một ký tự ít hơn \ r \ n? Chỉ trong Unix nó là một số ít \ n.
Vasili Syrakis

2
@Vasili: Bạn có thể lưu các tệp tốt chỉ với U + 000A giữa các dòng. PowerShell sẽ không phàn nàn. Bằng cách này, tôi đã viết trong câu trả lời. Ngắt dòng là một thuộc tính của tệp , không phải của hệ điều hành mà nó được sử dụng. Không ai nói rằng bạn không thể sử dụng kết thúc dòng Unix trên Windows.
Joey

@Joey Nếu bạn đã sử dụng một bản cài đặt mới của windows để thực hiện một số chương trình nhanh, bạn sẽ nhận thấy Notepad không chơi tốt với \ x0a
Stan Strum

9

Các Getđộng từ được ngụ ý. Điều này có thể rút ngắn bất kỳ Get-Frobđể chỉ Frob. Đối thủ thường xuyên là datehoặc random.

Lưu ý rằng điều này sẽ không hoạt động đúng trong một số trường hợp vì bạn có thể có các tiện ích GNU trong đường dẫn của mình (hoặc các chương trình gốc khác xung đột). Thứ tự tra cứu lệnh trong trường hợp đó dường như thích chương trình gốc hơn trước khi nó xem xét các lệnh ghép ngắn Get-bị loại bỏ:

PS Home:\> date

Freitag, 15. November 2013 07:13:45


PS Home:\> $Env:Path += ';D:\Users\Joey\Apps\GnuWin32\bin'
PS Home:\> date
Fr Nov 15 07:14:13 W. Europe Standard Time 2013

Điều này không hoàn toàn luôn làm việc ra như mong đợi. Tôi có một kịch bản bắt đầu bằng nal g Get-Randomđể lưu các ký tự sau này. Thay đổi nó để nal g Randomkhiến tập lệnh bị treo vô thời hạn (hoặc, ít nhất, mất một lượng thời gian không đáng có để xử lý - Tôi không đủ kiên nhẫn để chờ nó kết thúc, nhưng nó mất nhiều thời gian hơn so với hình thức ban đầu trước khi tôi phá thai).
Iszi

2
Hai Measure-Commandlời mời ngắn (100 lần Get-Randomso với random) cho tôi biết nó chậm hơn khoảng 500 lần. Tôi đã không biết rằng trước đây, thành thật mà nói. Nhưng thật tốt khi ghi nhớ nó, đặc biệt là các vòng lặp có nhiều lần lặp. Điều đó đang được nói, mã golf nên ngắn, không nhanh ( như đã nói, thật tệ khi phải chờ hai ngày để có câu trả lời cho vấn đề Project Euler).
Joey

1
Vấn đề của tôi là chạy 10.000 lần lặp kịch bản Monty Hall, mỗi lần yêu cầu ba lần lặp Get-Random. Thời gian xử lý tăng 50.000%, nhân lên trên 30.000 lượt chạy là khá khó chịu.
Iszi

Ồ Có vẻ như điều tương tự có thể đúng với bất kỳ bí danh nào. Đã thử nghiệm Get-Variableso với gvvà có một so sánh tương tự.
Iszi

1
Đó có thể là nó. Tôi đã làm một số phép toán và hình dung kịch bản Monty Hall của tôi sẽ mất khoảng 1,5 giờ (bình thường, 10-11 giây) để chạy mà không cần Get-. Đó là một cơn thịnh nộ khá lớn trong thời gian chạy với mức tiết kiệm chỉ 4 ký tự.
Iszi

8

for các vòng lặp có thể có bất cứ điều gì từ 0 đến ba câu lệnh trong tiêu đề của chúng:

Vòng lặp vô tận:

for(){}

Vòng lặp với khởi tạo:

for($n=0){}

Vòng lặp với điều kiện khởi tạo và kết thúc:

for($n=0;$n-lt7){}

Trong những trường hợp như vậy, dấu chấm phẩy bổ sung ở cuối có thể bị bỏ qua (nó được nêu rõ trong đặc tả ngôn ngữ , vì vậy nó không phải là một chi tiết triển khai) trái ngược với các ngôn ngữ giống như C luôn yêu cầu chính xác ba câu lệnh.

Điều này cũng làm cho whilemột chút ngắn hơn. So sánh

while(...){}

for(;...){}

Với phần thưởng được thêm vào mà bạn có thể dính vào một dòng trước đó (nếu có) forcũng không phải trả thêm chi phí (và thậm chí tiết kiệm một ký tự).


8

Nếu bạn đang chỉ định một mảng mà bạn biết sẽ chỉ có hai giá trị, đừng sử dụng lập chỉ mục.

Một cái gì đó như thế này:

$a="apple","orange"
$a[0] # apple
$a[1] # orange

Có thể dễ dàng biến thành thế này:

$a,$o="apple","orange"
$a # apple
$o # orange

Điều này cũng có thể hữu ích nếu bạn chỉ cần phần tử đầu tiên của một mảng:

$a,$b=1..10
$a # 1
$b # 2..10

Trong trường hợp này (với các chuỗi) $a="apple";$o="orange"là giống hệt nhau về chiều dài. Đó là các mảng dài hơn đôi khi có thể được tối ưu hóa khá độc đáo, ví dụ: bằng cách đặt tất cả các phần tử trong một chuỗi bằng dấu phân cách và sau đó sử dụng -split(tốt nhất là sử dụng khoảng trắng làm dấu phân cách vì khi đó unary -splitsẽ đủ).
Joey

8

Đúc thành chuỗi:

[string]$x

so với

"$x"

Việc truyền tới chuỗi như thế này cũng có thể được sử dụng để làm phẳng một chuỗi các chuỗi, thay vì nối nó:

$a = @('a','b','c')
$a -join ' '

so với

$a = @('a','b','c')
"$a"

Đúc một chuỗi thành một kiểu số:

[int]$x     [float]$x

so với

+$x

Cũng rất hữu ích khi biết rằng PowerShell luôn lấy loại toán hạng bên trái để xác định loại cuối cùng của biểu thức và chuyển đổi để áp dụng:

'1'+2    -> '12'
1+'2'    -> 3

có thể giúp xác định nơi không cần phôi.


6

Đừng quên rằng bạn không cần luôn cung cấp tên đầy đủ của một tham số và một số tham số là vị trí.

Get-Random -InputObject (0..10)

... có thể được cắt bớt để ...

Get-Random -I (0..10)

... bởi vì "tôi", trong trường hợp này, đủ để xác định duy nhất InputObjecttừ các tham số hợp lệ khác cho lệnh này.

Bạn có thể cắt nó thêm để ...

Get-Random (0..10)

... bởi vì InputObjectlà một tham số vị trí.

Đường ống thường ngắn hơn các đối tượng cho ăn như một tham số, đặc biệt là khi nó có thể loại bỏ sự cần thiết của dấu ngoặc đơn. Hãy cắt bớt trình tạo số ngẫu nhiên của chúng tôi hơn nữa ...

0..10|Get-Random

Ngoài ra, hãy cảnh giác với những cách khác để thực hiện điều tương tự, ngay cả khi bạn không thể thay đổi lệnh. Đối với trường hợp trên, bạn có thể làm điều này:

Get-Random 11

Hoặc, kết hợp một đề xuất khác *:

Random 11

** Lưu ý: Việc bỏ sót Get-từ một tên lệnh có thể làm mất thời gian chạy khoảng 50.000%. Không tệ nếu bạn chỉ cần lệnh một lần, nhưng hãy cẩn thận khi sử dụng nó trong các vòng lặp dài. *

Và đó là cách có thể hạ một lệnh đơn giản xuống còn một phần ba kích thước của nó.


6

Nhà điều hành ternary giả. Bạn có thể gán thẳng từ một iftuyên bố:

$z=if($x-eq$y){"truth"}else{"false"}

Nhưng bạn có thể sử dụng một mảng 2 phần tử và sử dụng thử nghiệm để lập chỉ mục vào nó. Kết quả $ falsey có được phần tử 0, $ kết quả trung thực lấy phần tử 1:

$z=("false","true")[$x-eq$y]

Lưu ý rằng điều này thực sự đang thực hiện lập chỉ mục mảng và nếu thử nghiệm dẫn đến một giá trị có thể được chuyển thành một số nguyên, bạn sẽ yêu cầu một mục bên ngoài giới hạn của mảng và nhận lại $ null, và sẽ cần phải thực hiện !(test)để buộc bỏ kết quả thành một bool, với các tùy chọn đảo ngược.


Đoạn mã đầu tiên không hoạt động tại một thời điểm (các phiên bản PowerShell cũ hơn), nếu tôi nhớ chính xác, khiến nó cần phải bọc lại $(). Về cơ bản, có một sự khác biệt trong việc sử dụng các đường ống được tạo từ các lệnh và câu lệnh làm biểu thức. Có vẻ như đã biến mất, ít nhất là trong PowerShell 5.
Joey

Ngoài ra, nếu các thành phần mảng là không tĩnh, cả hai đều được phân tích cú pháp và xử lý như là một phần của việc tạo mảng trước khi lập chỉ mục xảy ra và kết quả được gán. Ví dụ .
admBorkBork

6

Khi sử dụng số làm đối số cho toán tử nếu không yêu cầu chuỗi, bạn có thể sử dụng số trực tiếp. So sánh

...-join'0'

so với

...-join0

Làm việc với -splitlà tốt. Đối số luôn được chuyển đổi thành một chuỗi đầu tiên.


Để tham khảo, điều này làm việc với -replacelà tốt.
admBorkBork

-replacecũng hoạt động mà không có đối số thứ hai mà bạn muốn xóa trận đấu,
Joey

5

Giá trị tuyệt đối

Với

$n=-123

Thay vì

[math]::abs($n)

sử dụng

$n-replace'-'

Tất nhiên, khoản tiết kiệm bị hủy nếu cần dấu ngoặc đơn.


Hoặc nếu bạn cần kết quả ở phía bên trái của một nhà điều hành ;-)
Joey

5

Nếu bạn cần im lặng lỗi, biến thể rõ ràng sẽ là

try{ <# something that throws errors #> }catch{}

Tuy nhiên, đây là cách quá dài. Một biến thể ngắn hơn là chạy trykhối dưới dạng khối tập lệnh và chỉ chuyển hướng các lỗi thành một biến không đặt ( $nullsẽ là biến thông thường, nhưng vẫn còn quá dài):

.{ <# something that throws errors #> }2>$x

Điều này tiết kiệm năm byte có giá trị (nếu không phải là thế giới).


5

Sử dụng $ofs biến đặc biệt để thay đổi eparator O utput F ield S được sử dụng khi xâu chuỗi một mảng. Hữu ích nếu bạn cần chuyển đổi mảng thành chuỗi nhiều lần.

Ví dụ:

$a=1,2,3,4
$a-join',';$a-join','
$ofs=',';"$a";"$a"

Lưu 2+ n ký tự vào lần 2 -join, trong đó n là độ dài của dấu phân cách và lưu thêm 5+ n cho lần thứ 3 -joinvà mỗi ký tự sau đó.


1
Đáng buồn là rất hiếm khi hữu ích (ít nhất là trong việc chơi golf của tôi cho đến nay - tôi có xu hướng tước nó xuống chỉ còn một lần tham gia cuối cùng).
Joey

5

Biến tự động có booleans cho Đúng và Sai $true$falsenhưng bạn có thể nhận được kết quả tương tự bằng cách sử dụng toán tử không logic !và các số nguyên 0 và 1 (hoặc bất kỳ số nguyên khác không.)

PS C:\Users\matt> !1
False

PS C:\Users\matt> !0
True

Gần tất cả các biểu thức PowerShell có thể được đánh giá là booleans. Vì vậy, miễn là bạn nhận thức được cách đánh giá dữ liệu nhất định, bạn có thể nhận được booleans và không bao giờ cần phải phân loại chúng một cách rõ ràng. Hãy nhận biết giá trị LHS khi làm những việc này.

  • Số nguyên 0 là sai và số nguyên khác không được đánh giá là đúng.
  • chuỗi có độ dài khác không là chuỗi đúng và chuỗi rỗng hoặc null (và chính null) là sai.

Có những ví dụ khác nhưng bạn có thể dễ dàng kiểm tra bằng cách thực hiện một vai

PS C:\Users\matt> [bool]@(0)
False

1
Nhiều loại dữ liệu khác cũng có trạng thái tương tự. Các biến chưa được khởi tạo mặc định $null, đó là falsey. Chuỗi rỗng (và các biến được đặt thành chuỗi trống) là falsey. V.v. Điều này sau đó có thể được sử dụng để lập chỉ mục phím tắt thành một mảng (ví dụ: khi thực hiện if/ else), như đã được sử dụng trong FizzBuzz .
admBorkBork 14/03/2016

@TimmyD Rất đúng. Sử dụng ints chỉ ngắn hơn
Matt

@TimmyD Tôi muốn trả lời fizzbuzz cho đến khi tôi thấy bạn .... Không thể đánh bại điều đó .... ít nhất là chưa
Matt

Lưu ý rằng trong nhiều trường hợp bạn không thực sự cần a bool. Bạn có thể sử dụng 01là tốt. Chuyển đổi ngầm định giúp ích rất nhiều cho vấn đề đó (mà bạn thường có thể ép buộc với các nhà khai thác nhất định).
Joey

4

Invoke-ExpressionGet-Randomcũng có thể nhận đầu vào đường ống thay vì đối số.

Đối với iexđiều này cho phép lưu dấu ngoặc đơn trên một số biểu thức:

iex 1..5-join'+'   # won't work
iex(1..5-join'+')  # does work, but has extra parentheses
1..5-join'+'|iex   # doesn't need the parentheses

Trong trường hợp randomnày, cho phép một trường hợp phổ biến được tối ưu hóa một chút:

random -mi 10 31   # gets a random integer between 10 and 30
10..30|random      # much better :-)
(random 21)+10     # if needed in another expression that doesn't require extra
                   # parentheses

Cách sử dụng thứ hai chỉ đơn giản là chọn một mục từ danh sách. Đối -csố có thể được đưa ra để cho phép nhiều hơn một lựa chọn.


4

Xem xét việc lưu trữ các khối script lặp đi lặp lại trong các biến, thay vì sử dụng các hàm.

Tôi sẽ sử dụng điều này để lưu một số ký tự trong triển khai Rock, Paper, Kéo của tôi trước khi tôi nhận ra rằng việc viết lại hàm như một biến làm cho ngay cả biến không cần thiết. Điều này vẫn có thể hữu ích cho các tập lệnh khác, mặc dù bạn thực sự đang chạy cùng một mã nhiều lần.

function Hi{echo 'Hello, World!'};Hi

so với

$Hi={echo 'Hello, World!'};&$Hi

2
Hữu ích cho các hàm không lấy đối số. Nếu không, params(...)sẽ chiếm nhiều không gian hơn định nghĩa chức năng tiết kiệm. Liên quan: Sử dụng filterhơn functionkhi bạn có thể làm như vậy.
Joey

Bạn có thể sử dụng $argsđể tránh sự cần thiết cho params; tức là $x={$args[0]+2}(hoặc thậm chí $x={2+"$args"}); có thể lưu một ký tự hoặc 2 trong một số trường hợp. Bạn cũng có thể kết hợp điều này với một mẹo khác cho nhiều thông số:$x={$a,$b=$args;$a+$b+3}
JohnLBevan

4

Bạn có thể sử dụng $s|% t*ythay thế [char[]]$sđể phân tách một chuỗi thành mảng char. Đưa ra từ câu trả lời của TessellatingHeckler : % t*ymở rộng đến | ForEach-Object -Method ToCharArrayđẳng thức. của"$args".ToCharArray()

Ví dụ, so sánh

$s|% t*y

[char[]]$s

$s.ToCharArray()

$argsđặc biệt hữu ích với :$args|% t*y


1
Điều đó khá gọn gàng. Tôi cũng đã sử dụng %mánh khóe cho các thành viên một vài lần, nhưng hầu hết các môn đánh gôn của tôi đều có tính năng đó ;-). Đây cũng là một kỹ thuật chung: Hãy thử tìm kết hợp chữ cái / ký tự đại diện phù hợp với thuộc tính / phương thức bạn cần (và ngắn hơn so với thực tế).
Joey

Một ví dụ hữu ích khác từ câu trả lời: $s|% *perfor $s.toUpper()$s|% *werfor $s.toLower(). Tôi đồng ý rằng nó khá gọn gàng.
mazzy

Thêm một ví dụ nữa : |% t* "ddd\:hh\:mm\:ss"cho[TimeSpan].toString("ddd\:hh\:mm\:ss")
mazzy

Chà, đó chỉ là một sự lãng phí của trích dẫn, sau đó; bạn không cần chúng ở đây :-)
Joey


3

Sử dụng logic Boolean thay cho if-counter trong một vòng lặp

Giả sử bạn đang thêm tất cả các số chẵn từ 1 đến 10 ... 2+4+6+8+10=30

1..10|%{if($_%2-eq0){$o+=$_}};$o

Bạn có thể sử dụng phủ định Boolean để rút ngắn nó thành

1..10|%{if(!($_%2)){$o+=$_}};$o

để lưu một byte, nhưng thay vào đó, hãy sử dụng phép truyền Booleans ngầm cho ints và cuộn điều kiện vào bộ tích lũy

1..10|%{$o+=$_*!($_%2)};$o

Lưu 6 byte trong ví dụ này.


2
Chúa Giêsu Kitô. Tôi đang dự định làm điều này trong mã sản xuất tại nơi làm việc, các đồng nghiệp của tôi sẽ yêu tôi vì điều đó.
Chavez

3

Chuyển đổi số dấu phẩy động sang số nguyên trong PowerShell là một chút của một mỏ. Theo mặc định, chuyển đổi không làm tròn Ngân hàng mà không phải luôn cắt bớt số thập phân và để lại số nguyên nhỏ hơn hoặc luôn luôn làm tròn 0,5 đến số tiếp theo như mọi người, nó làm tròn một cách và tỷ lệ cược theo cách khác - điều này có thể đáng ngạc nhiên, ví dụ

PS C:\> [int]1.5
2

PS C:\> [int]2.5
2

và phá vỡ tính toán codegolf. Nhiều ngôn ngữ phổ biến khác thực hiện cắt ngắn, do đó, các câu hỏi về golf thường yêu cầu cắt ngắn. Bạn có thể đạt được [Math]::Floor()điều tốt nhất tiếp theo, nhưng hãy cẩn thận, điều này chỉ hành xử giống như cắt ngắn cho các số dương, nhưng nó sẽ lấy các số âm thấp hơn - xa hơn 0. [Math]::Truncate()là những gì bạn cần để đưa hành vi PS phù hợp với làm tròn mặc định của ngôn ngữ khác, nhưng đó là rất nhiều ký tự.

Regex thay thế các chữ số sau dấu thập phân có thể giúp lưu một vài ký tự:

[Math]::Truncate(1.5)
[Math]::Floor(1.5)
1.5-replace'\..*'

[Math]::Truncate($a)
[Math]::Floor($a)
$a-replace'\..*'
$a.split('.')[0]        # literal character split, not regex pattern split

3

Đảo ngược một mảng

Có ích trong rất nhiều thử thách trong đó đầu ra được nhân đôi trong một số thời trang.

Giả sử bạn có

$a=1,2,3,4,5

Phương pháp đảo ngược truyền thống là dài, nhàm chán và không để lại mảng trên đường ống để sử dụng ngay lập tức.

[array]::reverse($a)

Lập chỉ mục trực tiếp vào mảng theo thứ tự ngược lại tiết kiệm một vài byte, vì nó để lại kết quả trên đường ống, nhưng vẫn còn khá dài:

$a[($a.count-1)..0]

Thay vào đó, hãy thử một vòng lặp

$a|%{$a[-++$i]}

lập chỉ mục ngược hoạt động tốt khi có giới hạn trên cho số đếm
Joey

3

Bắt đầu với PowerShell Core 6, bạn cũng có thể sử dụng phạm vi cho các ký tự:

'a'..'z'

có thể thay thế rườm rà hơn nhiều

0..25|%{[char]($_+97)}

Oh, điều này sẽ đi vào rất tiện dụng.
admBorkBork

1
[char[]](65..90)cũng là một cách thuận tiện để tạo bảng chữ cái
Veskah
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.