我正在开发一个PowerShell脚本,我在其中输入一个长字符串(来自CSV文件),格式为:
第一组名称
第二组名称
第三组名称......
我试图用
解析它($entry.'Group Name').split("`n ") | %{
if ($_) {
# Do something with the group name
$_
}
}
我希望输出如下:
第一组名称
第二组名称
第三组名称
...
但它出现了:
组别
一个
姓名
集团
两个
...
答案 0 :(得分:6)
通过接受Bacon Bits' helpful answer,您已经表明它已经解决了您的问题,但是当您通过"`n "
时,仍然会留下您意味着的问题 - 即,一个2个字符的PowerShell字符串 - [string]
类.Split()
方法。
此答案通常使用PowerShell自己的-split
运算符而不是.Split()
>方法 ,因为它:
-split
与.Split()
方法之间存在关键差异:
默认情况下, -split
使用正则表达式 来指定拆分条件;使用'SimpleMatch'
选项作为第3个RHS参数来使用字符串文字;相比之下,.Split()
方法仅接受文字。
还有一个 一元形式的-split
,它可以通过任何空格分割而忽略前导和尾随空格,类似到awk
的默认行为;这相当于调用'...'.Split([string[]] $null, 'RemoveEmptyEntries')
-split
默认情况下-csplit
表单进行区分大小写的匹配;相比之下,.Split()
总是案例 - 敏感。
您可以使用可选的第二个参数限制返回的令牌数,该参数仅拆分输入字符串的 part ,报告输入字符串的其余部分在返回数组的最后一个元素中;相比之下,.Split()
没有这样的选择。
-split
接受数组值 LHS ,返回因拆分而导致的令牌数组的连接 LHS的要素。
-split
隐式将LHS转换为字符串;相比之下,.Split()
只能在已经[string]
的内容上调用。
有关完整报道,请参阅Get-Help about_Split
。
.Split()
方法有一个优点:它比<{1}}运算符更快;所以,如果 -split
的功能在给定的场景中足够,你就可以加快速度。
<强>示例:强>
注意:在下面使用正则表达式的示例中,使用单引号字符串,LF字符表示为正则表达式转义序列 {{ 1}}而不是PowerShell在任何双引号字符串中支持的.Split()
转义序列,因为最好将正则表达式指定为单引号字符串,避免在PowerShell预先扩展的内容与\n
最终看到的内容之间产生混淆。
以 1}}(LF)以及 `n
(单个空格):
-split
相当于"`n"
按字符串 拆分,指定为正则表达式:" "
:
"one two`n three four" -split '[\n ]'
相当于@( 'one', 'two', '', 'three', 'four' )
使用"`n "
选项按字符串文字 :"one two`n three four" -split '\n '
拆分:
@( 'one two', 'three four' )
与上述相同;请注意"`n "
是to-tokens-to-return参数,必须在此处出于语法原因指定; SimpleMatch
表示应返回所有令牌。 在分隔符正则表达式中使用捕获组("one two`n three four" -split "`n ", 0, 'SimpleMatch'
)以在结果数组中包含(部分)分隔符:
0
相当于0
(...)
)来使分隔符成为元素的一部分:{{1产生相当于'a/b' -split '(/)'
限制令牌数量:
@('a', '/', 'b')
相当于
(?=...)
,即第三个令牌收到输入字符串的剩余部分。
警告:通过分隔符正则表达式中的捕获组捕获的(部分)分隔符的元素不计入指定的限制;例如,
'a/b/c' -split '(?=/)'
会产生@( 'a', '/b', '/c' )
,即 3 元素。
按任意一行空格(一元格式)拆分:
'one two three four' -split ' ', 3
相当于@( 'one', 'two', 'three four' )
'a/b/c' -split '(/)', 2
- 方法陷阱:访问.NET Framework的方法如果需要是一个很好的选择,它允许您在PowerShell中执行大多数编译的.NET语言可以执行的操作。
但是,PowerShell必须在幕后做一些通常有用的事情,但也可能是陷阱:
例如,@( 'a', '/', 'b/c' )
会导致PowerShell在调用之前将字符串 -split "`n one `n`n two `t `t three`n`n"
隐式转换为字符数组(@( 'one', 'two', 'three' )
) String.Split()
(方法重载中最接近的匹配),这可能是意外的。
您的意图可能是由 string 'foo'.Split("`n ")
拆分,但调用的方法重载最终会将您的字符串解释为aa 个别字符集任何一个其中的分割输入。
顺便提一下,跨平台的PowerShell Core 版本有一个额外的"`n "
重载, 现在直接采用[char[]]
参数,所以同样的呼叫在那里表现不同。
在PowerShell控制范围之外的这种改变行为本身就是一个很好的理由,更喜欢仅使用PowerShell的解决方案 - 解释为什么这些更改不在PowerShell的控制范围内,请参阅{{ 3}}
你可以通过明确的输入来避免这些陷阱,但这既麻烦又容易忘记。
一个很好的例子:
在 Windows PowerShell中,如果您真的想通过 string .Split()
进行拆分,那么您需要这样做:
"`n "
注意必要的强制转换为.Split()
- 即使只传递了一个字符串 - 并且必须使用选项参数([string]
)。
相反,如果您想在PowerShell Core 中按字符集进行拆分:
"`n "
如果没有PS> "one`n two".Split([string[]] "`n ", 'None')
one
two
强制转换,[string[]
将被视为单个字符串以进行拆分。
答案 1 :(得分:2)
如果我正确阅读,您对.Split
的调用会同时传递`n
和空格字符。因此,您实际上是要求PowerShell将"Group One Name"
之类的字符串转换为@("Group", "One", "Name")
之类的列表。
如果$entry
是单个记录,并且您为“Group One Name”,“Group Two Name”和“Group Three Name”中的每一个运行此行一次,那么您可能不需要完全致电.Split
- 只需直接使用$entry.'Group Name'
。
答案 2 :(得分:1)
String.Split()
中的字符串参数是要拆分的字符列表,而不是要匹配然后拆分的字符序列。您现有的代码将在换行符上拆分,并将在空格上拆分。
如果您只想在换行符上拆分,请使用:
.split("`n")
如果要分隔换行符的字符序列,后面紧跟空格,可以使用Regex.Split()
:
[Regex]::Split($entry.'Group Name',"`n ") | ...
或者,您可以使用-split
运算符,该运算符也按字符串而不是字符列表进行拆分:
$entry.'Group Name' -split "`n "
答案 3 :(得分:0)
考虑使用开关语句。就个人而言,我认为使用一个可以使您的代码更具可读性/可维护性:
[System.Array] $arrCSVData = @();
$arrCSVData = Import-CSV -LiteralPath '---your .csv path ---';
switch ( $arrCSVData ) {
{ $_.'Group Name' -eq 'Group One Name' } {
# Do something with group #1.
break;
}
{ $_.'Group Name' -eq 'Group Two Name' } {
# Do something with group #2.
break;
}
} #switch
这显然缺少CSV导入的错误处理......
答案 4 :(得分:0)
如果我理解正确,您只需要从现有代码中删除空格。
.split("`n ")
应该是:
.split("`n")
现有代码使用新行和空间作为分隔字符串的分隔符。
答案 5 :(得分:0)
我认为你需要`r Windows转义符来换行。