Answers:
您可以在PowerShell中跳过很多空格。如果感觉不需要它,则很有可能不需要它。这在比较中特别有用。
例:
$x-eq$i-and$x-ne9
与
$x -eq $i -and $x -ne 9
如果您需要根据可能有多个结果的单个测试的结果来分支脚本,switch
则有时可以匹配或击败if语句。
示例(切换与if / else-并列):
if($x%2-eq0){'even'}else{'odd'}
与
switch($x%2){0{'even'}1{'odd'}}
或(切换vs. if / elseif / else-切换胜15分):
if($x%2-eq0){'even'}elseif($x%2-eq1){'odd'}else{'error'}
与
switch($x%2){0{'even'}1{'odd'}2{'error'}}
如果开关实际上是基于某些数学结果的,例如上面的模运算,则可以将整个开关替换为数组。在这里,它会再保存13个字符,并且比原始的二选项if / else语句还要短。(感谢Danko Durbic的帮助。)
('even','odd','error')[$x%2]
如果您将大量使用特定命令,尤其是没有预先存在的速记别名的命令,请尽早设置单字符别名。
例:
nal g Get-Random;g 10;g 10;g 10
与
Get-Random 10;Get-Random 10;Get-Random 10
('even','odd')[$x%2]
仅供参考。
给定数组时,开关可以像循环一样工作。例如:
$FooBarMeh='a','b','c'
switch ($FooBarMeh)
{
'a'{'FOO'}
'b'{'BAR'}
default{'MEH'}
}
将输出:
FOO
BAR
MEH
我不确定这在什么地方有用,但我希望一段时间后对某些人有用。
ForEach-Object
和a时switch
,它都很方便。例如,(在现实世界中)代码非常适合编写文本文件的快速解析器,您需要根据行匹配的正则表达式执行不同的操作。
switch -File $path
是
是否要查找值集合的最大值或最小值?试过了
(...|measure -ma).Maximum
要么
(...|measure -mi).Minimum
已经?
只需排序并使用最后一项或第一项即可:
(...|sort)[-1] # maximum
(...|sort)[0] # minimum
0
,1
,2
,3
,4
,5
,6
,7
,8
或者9
,它会保存一个字节写的已知长度来代替-1
。
遗憾的是,与参数不同,.
通常不能将属性/方法(用点访问的任何内容)简化为明确的形式。
但是某些cmdlet可以对属性名称进行操作并采用通配符,并且鲜为人知的参数集%
和?
很有用。
通常,我们传入一个脚本块,并使用来引用该项目$_
,但是其中的另一种形式是使用属性名称,并且它接受通配符。
$o|select Le*
$o|%{$_.Length}
对于像.Length
我们这样Length
的属性,由于数组本身是属性,因此不能使用通常在数组上可用的v3魔术,因此可以使用上述两个获取单个成员的长度。该select
进来一点点短。
但是%
可以直接采用属性名称并返回该值:
$a|% Length
可以使用通配符将其缩短。通配符必须解析为单个属性(或方法,稍后会详细介绍),因此,通配符将抛出有用的错误,并指出可能会解析为的成员。
对于Length
,Le*
通常是最短的。即使在单个字符串上,此方法也比仅使用该属性短1个字节。
$a.Length # 9 #(doesn't work on array)
$a|%{$_.Length} # 15
$a|% Le* # 8
但是根据您在做什么,情况可能会更糟。您可以做,$a.Length*5
但要使用管道表达式来做,就必须将其包装起来($a|% Le*)*5
;如果它是针对数组的,也许仍然值得,但是重点是它并不总是适合作为直接替换。
它也适用于方法,您可以省略()
,使全名具有相同的长度,但有时必须包装它,因此与上述相同。该方法必须有一个不带参数的重载(您可以通过将参数放在方法名称之后来传递参数,这确实不错):
$a.ToUpper() # 12
$a|% *per # 9
带参数:
'gaga'-replace'g','r' # 21
'gaga'|% *ce g r # 16
这些-replace
操作与操作符执行正则表达式替换并不完全相同,但是如果您只是在进行字符串替换,则使用该方法可以(现在)更短一些。这有助于将字符串作为cmdlet参数而不是方法参数,因此不需要将其引起来。
?
也可以采用(部分)属性名称,并对其应用“运算符”(以开关参数的形式)。同样,Where-Object
如果属性名称足够长且唯一,则它可以比使用标准脚本块方法短。
$a|?{$_.Length-gt5} # 19
$a|? Le* -GT 5 # 14
($a|% Le*)-gt5 # 14 - Lengths, not objs
.ToString()
!
分号和换行符可以互换。高尔夫球代码如果不卡在一行中,通常更具可读性。并且长度仍然相同(前提是您使用U + 000A作为PowerShell可以毫无问题地处理的换行符)。
该Get
动词是隐含的。这可以缩短任何Get-Frob
时间Frob
。经常竞争者是date
或random
。
请注意,这在某些情况下将无法正常工作,因为您的路径(或其他冲突的本机程序)中可能装有GNU实用程序。在这种情况下,命令查找顺序似乎更喜欢本机程序,然后再考虑Get-
删除的cmdlet :
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
nal g Get-Random
其后开始保存字符。将其更改为nal g Random
会导致脚本无限期挂起(或至少需要花费非常长的时间来处理-我没有耐心等待它结束,但是它比原始形式要花几个数量级在我中止之前)。
Measure-Command
调用(100次Get-Random
对random
)告诉我这是关于慢500倍。老实说,我以前不知道。但最好记住这一点,尤其是在具有多次迭代的循环中。话虽如此,打高尔夫球的代码应该简短而不是太快(也就是说,必须等待两天才能解决欧拉计划问题)。
Get-Variable
与,gv
并获得了类似的比较。
Get-
。这在运行时非常麻烦,仅节省了4个字符。
如果要分配的数组只有两个值,请不要使用索引。
像这样:
$a="apple","orange"
$a[0] # apple
$a[1] # orange
可以很容易地变成这样:
$a,$o="apple","orange"
$a # apple
$o # orange
如果您只需要数组的第一个元素,这也可能很有用:
$a,$b=1..10
$a # 1
$b # 2..10
$a="apple";$o="orange"
的长度是相同的。较长的数组有时可以很好地进行优化,例如,通过将所有元素放在带有分隔符的字符串中,然后使用-split
(最好使用空格作为分隔符,因为一元-split
就足够了)。
不要忘了,您不一定总是需要提供参数的全名,并且某些参数是位置性的。
Get-Random -InputObject (0..10)
...可以修整为...
Get-Random -I (0..10)
...因为在这种情况下,“ I”足以InputObject
从该命令的其他有效参数中唯一标识。
您可以将其进一步修剪为...
Get-Random (0..10)
...因为InputObject
是位置参数。
管道通常比作为参数的对象短,特别是当管道可以消除括号时。让我们进一步修剪随机数生成器...
0..10|Get-Random
即使您无法更改命令,也要注意其他方法来完成同一件事。对于上述情况,您可以执行以下操作:
Get-Random 11
或者,结合其他建议 *:
Random 11
**注意:省略Get-
命令名称可能会使运行时间膨胀约50,000%。如果只需要一次该命令,但要在长循环中小心使用,就可以了。*
这就是如何将简单命令压缩到其大小的三分之一。
伪三元运算符。您可以直接从if
语句中分配:
$z=if($x-eq$y){"truth"}else{"false"}
但是您可以使用2元素数组,并使用测试对其进行索引。$ falsey结果获取元素0,$ truthy结果获取元素1:
$z=("false","true")[$x-eq$y]
注意 这确实是在做数组索引,并且如果测试得出的值可以转换为整数,则您将要求在数组范围之外的项并获得$ null,并且需要!(test)
强制执行将结果转换为布尔值,并反转选项。
$()
。使用由命令和语句构成的管道作为表达式本质上是有区别的。至少在PowerShell 5中似乎已经消失了
当使用数字作为运算符的参数(否则需要字符串)时,可以直接使用数字。相比
...-join'0'
与
...-join0
工程与-split
为好。参数总是先转换为字符串。
-replace
。
-replace
也不需要您要删除匹配项的第二个参数,也可以使用
自动变量有真布尔和假作为$true
和$false
,但你可以使用逻辑不是运营商处获得类似的结果!
和整数0和1(或任何非零整数)。
PS C:\Users\matt> !1
False
PS C:\Users\matt> !0
True
几乎所有PowerShell表达式都可以被评估为布尔值。因此,只要您知道如何评估某些数据,就可以获取布尔值,而无需显式转换它们。执行这些操作时,请注意LHS值。
还有其他示例,但是您可以通过强制转换轻松地进行测试
PS C:\Users\matt> [bool]@(0)
False
$null
,为false。空字符串(并将变量设置为空字符串)为false。等等,然后可以像在FizzBuzz中那样,使用它来快速索引到数组中(例如,执行if
/时else
)。
int
s会更短一些
bool
。您也可以使用0
和1
。隐式转换在这方面有很大帮助(您通常可以使用某些运算符来强制转换)。
Invoke-Expression
并且Get-Random
还可以获得管道输入而不是参数。
为此,iex
可以在某些表达式上保存括号:
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
在random
这种情况下,可以对常见情况进行一些优化:
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
可以给出该参数以允许多个选择。
考虑将重复的脚本块存储在变量中,而不是使用函数。
在我意识到将函数重写为变量甚至使该变量变得不必要之前,我将使用它在我的Rock,Paper,Scissors实现中保存一些字符。但是,这对于其他脚本仍然很有用,因为在这些脚本中您实际上多次运行相同的代码。
function Hi{echo 'Hello, World!'};Hi
与
$Hi={echo 'Hello, World!'};&$Hi
params(...)
将占用比函数定义节省的空间更多的空间。相关阅读:使用filter
过function
的时候,你可以这样做。
$args
可以避免使用params
;即$x={$args[0]+2}
(甚至$x={2+"$args"}
);在某些情况下可能会保存一个字符或2个字符。您还可以将其与另一个用于多个参数的技巧结合起来:$x={$a,$b=$args;$a+$b+3}
您可以使用$s|% t*y
,而不是[char[]]$s
分裂的字符串的字符数组。从TessellatingHeckler的答案中得出:% t*y
扩展为| ForEach-Object -Method ToCharArray
等效。的"$args".ToCharArray()
例如比较
$s|% t*y
和
[char[]]$s
和
$s.ToCharArray()
它$args
特别适用于:$args|% t*y
%
为会员使用过几次技巧,但是我的大多数高尔夫活动都以;-)为特色。这也是一种通用技术:尝试找到与所需属性/方法相匹配的字母/通配符组合(并且比真实事物短)。
$s|% *per
for $s.toUpper()
和$s|% *wer
for $s.toLower()
。我同意那很整洁。
假设您要将所有偶数加到1到10 ... 2+4+6+8+10=30
1..10|%{if($_%2-eq0){$o+=$_}};$o
您可以使用布尔否定符将其缩短为
1..10|%{if(!($_%2)){$o+=$_}};$o
保存一个字节,但是如何使用布尔值的隐式转换为整数,并将条件转换为累加器
1..10|%{$o+=$_*!($_%2)};$o
在此示例中节省6个字节。
在PowerShell中将浮点数转换为整数有点麻烦。默认情况下,该转换会进行“ 银行取整”操作,该操作并不总是舍去小数并保留较小的整数,或者像人们随便做的那样始终将0.5向上舍入到下一个数字,它会以一种方式四舍五入为偶数,以另一种方式为奇数-这可以令人惊讶,例如
PS C:\> [int]1.5
2
PS C:\> [int]2.5
2
并中断codegolf计算。许多其他通用语言也会进行截断取整,因此高尔夫球问题通常需要截断。您可能会碰到[Math]::Floor()
下一件最好的事情,但是请注意,这仅与正数截断的行为相同,但是负数要低一些-远离零。[Math]::Truncate()
您需要使PS行为与其他语言的默认四舍五入保持一致,但这是很多字符。
正则表达式替换小数点后的数字可以帮助节省几个字符:
[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
假设你有
$a=1,2,3,4,5
传统的反转方法很长,很无聊,并且不会将数组留在管道上立即使用。
[array]::reverse($a)
以相反的顺序直接索引到数组中可以节省一些字节,因为它将结果留在管道上,但是仍然很长:
$a[($a.count-1)..0]
而是尝试循环
$a|%{$a[-++$i]}
从PowerShell Core 6开始,您还可以使用字符范围:
'a'..'z'
可以代替繁琐的工作
0..25|%{[char]($_+97)}
[char[]](65..90)
也是生成字母的便捷方法