在 PowerShell 中使用分隔符连接部件的最佳方式
Posted
技术标签:
【中文标题】在 PowerShell 中使用分隔符连接部件的最佳方式【英文标题】:Best way to join parts with a separator in PowerShell 【发布时间】:2012-03-24 12:17:16 【问题描述】:我需要将多个 Url 元素连接成一个字符串,所以我编写了通用的 Join-Parts 函数:
filter Skip-Null $_|? $_
function Join-Parts
param
(
$Parts = $null,
$Separator = ''
)
[String]$s = ''
$Parts | Skip-Null | ForEach-Object
$v = $_.ToString()
if ($s -ne '')
if (-not ($s.EndsWith($Separator)))
if (-not ($v.StartsWith($Separator)))
$s += $Separator
$s += $v
elseif ($v.StartsWith($Separator))
$s += $v.SubString($Separator.Length)
else
$s = $v
$s
Join-Parts -Separator '/' -Parts 'http://mysite','sub/subsub','/one/two/three'
Join-Parts -Separator '/' -Parts 'http://mysite',$null,'one/two/three'
Join-Parts -Separator '/' -Parts 'http://mysite','','/one/two/three'
Join-Parts -Separator '/' -Parts 'http://mysite/','',$null,'/one/two/three'
Join-Parts 1,2,'',3,4
按预期返回:
http://mysite/sub/subsub/one/two/three
http://mysite/one/two/three
http://mysite/one/two/three
http://mysite/one/two/three
1234
我觉得这不是最聪明的方法。有什么更好的方法吗?
更新
根据@sorens 的回答,我将函数更改为:
function Join-Parts
param
(
$Parts = $null,
$Separator = ''
)
($Parts | ? $_ | % ([string]$_).trim($Separator) | ? $_ ) -join $Separator
【问题讨论】:
你考虑过URIBuilder吗? 【参考方案1】:从Path.Combine for URLs?的最佳答案中汲取灵感
function Combine-UriParts ($base, $path)
return [Uri]::new([Uri]::new($base), $path).ToString()
应该很容易扩展到多个部分
【讨论】:
【参考方案2】:Powershell 有一个-join
运算符。如需帮助,请输入帮助about_join
【讨论】:
【参考方案3】:基于@mjolinor 的答案,这条单线通过了您问题中的所有测试:
($parts | ? $_ | % ([string]$_).trim('/') | ? $_ ) -join '/'
如果您并不真正关心最后一个测试用例 (1,2,'',3,4)
并且可以假设所有输入都是字符串,您可以将其缩短为:
($parts | ? $_ | % $_.trim('/') | ? $_ ) -join '/'
请注意,我有 两个 空/空过滤器 (? $_ )
:第一个从输入中去除空值或空字符串,它使用空字符串 ('http:/fdfdfddf','','aa/bb')
纠正您的测试用例。第二个也是必要的,通过 trim 函数捕获输入 reduced 为空。
如果你真的想对它很挑剔,你应该再添加一个修剪来消除只有空格的值,因为它们可能是不需要的:
($parts | ? $_ | % $_.trim('/').trim() | ? $_ ) -join '/'
对于最后一个,这些测试用例输入也将返回http://mysite/one/two
:
$parts = 'http://mysite','' ,'one/two' # empty
$parts = 'http://mysite',' ','one/two' # whitespace
$parts = 'http://mysite',' /','one/two' # trailing virgule
$parts = 'http://mysite','/ ','one/two' # leading virgule
$parts = 'http://mysite','/ /','one/two' # double virgule
【讨论】:
@SergevandenOever,现在你让我想知道:-) 你几个月前就接受了我的回答,现在你也换了一个与几个月前不同的答案。然而,mjolinar 的答案只通过了您问题中五个测试用例中的两个,而我的则通过了所有五个。我错过了什么吗? 你完全正确!我在小屏幕上检查我没有回答的问题,忽略了我已经接受了你的答案!我换回来了!对不起:-) 我不赞成这个解决方案有一个非常重要的原因:可读性。没有高级 PowerShell 知识的任何人都无法阅读此解决方案,因此不应传播。 看起来在所有情况下第一个? $_
都是多余的。
@roxton 首先感谢您注意到 PowerShell 已经发展,因此不再需要第一个 null/empty 过滤器!虽然我很欣赏你提出编辑建议的热情,但我拒绝了它,因为它失去了一些背景——阅读仍然显示过滤器的原始帖子的人会有点摸不着头脑,不知道他是如何从这里走到那里的。这就是为什么我认为您在上面的清晰、简洁的评论(它是多余的)更好。再次感谢!【参考方案4】:
这是一个使用 UriBuilder 类创建 URL 的示例:
$builder = New-Object System.UriBuilder
$builder.Host = "www.myhost.com"
$builder.Path = ('folder', 'subfolder', 'page.aspx' -join '/')
$builder.Port = 8443
$builder.Scheme = 'https'
$builder.ToString()
输出:
https://www.myhost.com:8443/folder/subfolder/page.aspx
更新 - 这里有一个小功能,应该能够结合你的 URL 部分:
function Join-Parts
param ([string[]] $Parts, [string] $Seperator = '')
$search = '(?<!:)' + [regex]::Escape($Seperator) + '+' #Replace multiples except in front of a colon for URLs.
$replace = $Seperator
($Parts | ? $_ -and $_.Trim().Length) -join $Seperator -replace $search, $replace
Join-Parts ('http://mysite','sub/subsub','/one/two/three') '/'
Join-Parts ('http://mysite',$null,'one/two/three') '/'
Join-Parts ('http://mysite','','/one/two/three') '/'
Join-Parts (1,2,'',3,4) ','
输出:
http://mysite/sub/subsub/one/two/three
http://mysite/one/two/three
http://mysite/one/two/three
1,2,3,4
【讨论】:
不知道这门课!尝试使用 System.Uri。多个部分的路径仍然存在问题。需要 mjoliner 他的答案!不过谢谢! @SergevandenOever 是的 System.Uri 是不可变版本。您可以通过访问 Uri 属性$builder.Uri
从构建器获取 System.Uri 对象。
@SergevandenOever 我在答案中添加了一个小功能,应该能够组合您的片段。
嗨,安迪,感谢您提供的额外功能。不过看起来有点贵。 @msorens 的答案看起来轻松多了,所以我选择了他的答案。感谢您对我的问题的所有精彩思考!【参考方案5】:
你可以这样做:
($parts | foreach $_.trim('/')) -join '/'
【讨论】:
我无法编辑,但完美的答案。必须是: ($parts | foreach $_.trim('/')) -join '/' 谢谢。我错过了那个支架。 但仍然不完全正确:('http:/fdfdfddf','','aa/bb' | ForEach-Object $_.trim('/')) -join '/'变成http://fdfdfddf//aa/bb,注意多余的'/' GIGO 是什么意思? :-) 啊……垃圾进,垃圾出……但这正是我的问题:-) 我有多个部分来自 xml 配置文件。 我可以理解有多个部分。您的任何样本数据都没有表明它们会像那个烂摊子那样畸形。以上是关于在 PowerShell 中使用分隔符连接部件的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章
在 Powershell 中,按记录类型拆分大型文本文件的最有效方法是啥?