为了账号安全,请及时绑定邮箱和手机立即绑定

在PowerShell中在新行上用空格分隔字符串

/ 猿问

在PowerShell中在新行上用空格分隔字符串

精慕HU 2019-12-06 12:49:53

我正在使用PowerShell脚本,在该脚本中,我使用以下格式输入长字符串(来自CSV文件):


第一组名称

第二组名称

第三组名称

...


我正在尝试与解析


($entry.'Group Name').split("`n ") | %{

    if ($_) {

        # Do something with the group name

        $_

    }

}

我想得到像这样的输出:


第一组名称

第二组名称

第三组名称

...


但结果如下:


集团

的一个

名称

两个

...


查看完整描述

3 回答

?
蓝山帝景

中的string参数String.Split()是要分割的字符列表,而不是要匹配然后分割的字符序列。您现有的代码将在换行符上分割,并在空间上分割。


如果只想在换行符上分割,请使用:


.split("`n")

如果要在换行符的字符序列上进行分割,然后紧跟一个空格,则可以使用Regex.Split():


[Regex]::Split($entry.'Group Name',"`n ") | ...

或者,您可以使用-split运算符,该运算符还会按字符串而不是字符列表进行拆分:


$entry.'Group Name' -split "`n "


查看完整回答
反对 2019-12-06
?
123456qqq

通过接受Bacon Bits的有用答案,您已经表明它可以解决您的问题,但这仍然使您质疑将类字符传递给类方法时的含义"`n "(即2个字符的PowerShell字符串)。[string].Split()


该答案为常规使用PowerShell自己的-split 运算符而不是.Split() method提供了理由,因为它可以:


使用常规PowerShell运算符语法

提供更多功能

惊喜少

和方法之间-split.Split()有一些主要区别:


默认情况下,-split使用正则表达式指定拆分条件;使用该'SimpleMatch'选项作为第三个RHS参数,改为使用字符串文字;相比之下,该.Split()方法仅接受文字。


还有一种一元形式,-split可以按任意空格分隔,并忽略前导和尾随空格,类似于awk的默认行为;这相当于打电话'...'.Split([string[]] $null, 'RemoveEmptyEntries')


-split是区分不敏感默认(如在典型的PowerShell); 使用-csplit表格进行区分大小写的匹配;相比之下,.Split()是总是区分大小写。


您可以使用可选的第二个参数限制返回的令牌数,该参数仅拆分部分输入字符串,并在return数组的最后一个元素中报告其余的输入字符串。相比之下,.Split()没有这种选择。


-split接受一个数组值的 LHS,返回由拆分LHS的元素导致的令牌数组的串联。


-split 将LHS 隐式转换为字符串;相反,.Split()只能在已经是的东西上调用[string]。


有关完整的故事,请参见Get-Help about_Split。


但是,该.Split()方法有一个优点:它比运算符要快-split;因此,如果 .Split()在给定的情况下的功能已足够,则可以加快处理速度。


例子:


注意:在下面的使用正则表达式的示例中,使用单引号字符串,其中LF字符表示为正则表达式转义序列, \n而不是`nPowerShell在任何双引号字符串中支持的转义序列,因为最好指定正则表达式作为单引号字符串,以避免在PowerShell扩展的内容和-split最终看到的内容之间造成混淆。


分割通过任何在集合的字符,作为正则表达式:"`n"(LF) ,并且还 " "(单个空格):


"one two`n three four" -split '[\n ]' 产生相当于

@( 'one', 'two', '', 'three', 'four' )

由分割字符串,指定为正则表达式:"`n ":


"one two`n three four" -split '\n ' 产生相当于

@( 'one two', 'three four' )

用字符串文字:分割"`n ",使用SimpleMatch选项:


"one two`n three four" -split "`n ", 0, 'SimpleMatch'产生与上述相同的结果;请注意,这0是要返回的令牌数参数,出于语法原因,此处必须指定该参数;0表示应返回所有令牌。

在分隔符正则表达式中使用捕获组((...))在结果数组中包括分隔符(的一部分):


'a/b' -split '(/)' 产生相当于 @('a', '/', 'b')

或者,使用正前向断言((?=...))以使分离器的元件的部分:'a/b/c' -split '(?=/)'产生的等效的

@( 'a', '/b', '/c' )

限制令牌数量:


'one two three four' -split ' ', 3产生等价的

@( 'one', 'two', 'three four' ),即第三个令牌收到了输入字符串的其余部分。


注意:作为通过分隔符正则表达式中的捕获组捕获的分隔符(的一部分)的元素不计入指定的限制;例如

'a/b/c' -split '(/)', 2yields @( 'a', '/', 'b/c' ),即总共3个元素。


按任意空格分隔(一元形式):


-split "`n  one   `n`n two `t  `t three`n`n" 产生相当于

@( 'one', 'two', 'three' )

String.Split()-方法陷阱:

如果需要的话,可以访问.NET Framework的方法是一个很好的选择,它使您可以在PowerShell中完成大多数已编译的.NET语言可以执行的操作。

但是,PowerShell必须在幕后做一些通常有帮助的事情,但也可能是陷阱:


例如,'foo'.Split("`n ")导致PowerShell 在调用之前将字符串 隐式转换"`n "为字符数组([char[]]).Split()(方法重载之间最接近的匹配),这可能是意外的。


您的意图可能是按字符串 拆分"`n ",但是调用的方法重载最终将您的字符串解释为一组单独的字符,可以使用任意一个字符来拆分输入。


顺便说一句,跨平台的PowerShell Core版本具有一个额外的.Split()重载,该重载现在确实直接采用了一个[string]参数,因此同一调用在那里的行为有所不同。


在PowerShell的控制范围之外发生的这种变化行为本身就是选择仅使用PowerShell的解决方案的一个很好的理由 -有关为何此类更改不在PowerShell的控制范围内的解释,请参见GitHub问题。


您可以通过显式键入来避免此类陷阱,但这既麻烦又容易忘记。

例子:


在Windows PowerShell中,如果您确实想按字符串 拆分"`n ",则需要执行以下操作:


PS> "one`n two".Split([string[]] "`n ", 'None')

one

two

请注意,[string[]即使仅传递了一个字符串,也必须进行强制转换,并必须使用option参数(None)。


相反,如果要在PowerShell Core中按一组字符拆分:


PS> "one`ntwo three".Split([char[]] "`n ")

one

two

three

没有[char[]]强制转换,"`n "将被视为拆分的单个字符串。


查看完整回答
反对 2019-12-06
?
湖上湖

如果我没看错,则您的呼叫同时.Split传入`n了空格字符。因此,您实际上是在要求PowerShell将一个类似的字符串"Group One Name"转换成一个类似这样的列表@("Group", "One", "Name")

如果$entry是单个记录,并且您对“组名”,“组二名”和“组三名”中的每一个都运行一次此行,那么您可能根本不需要调用.Split-只需使用$entry.'Group Name'直。


查看完整回答
反对 2019-12-06
  • 3 回答
  • 0 关注
  • 398 浏览
慕课专栏
更多

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信