使用 PowerShell 拆分字符串并对每个令牌执行一些操作

Posted

技术标签:

【中文标题】使用 PowerShell 拆分字符串并对每个令牌执行一些操作【英文标题】:Split string with PowerShell and do something with each token 【发布时间】:2012-07-06 02:29:48 【问题描述】:

我想在空格上分割管道的每一行,然后在自己的行上打印每个标记。

我意识到我可以使用以下方法得到这个结果:

(cat someFileInsteadOfAPipe).split(" ")

但我想要更多的灵活性。我希望能够对每个令牌做任何事情。 (我曾经在 Unix 上使用 AWK,我正在尝试获得相同的功能。)

我目前有:

echo "Once upon a time there were three little pigs" | %$data = $_.split(" "); Write-Output "$($data[0]) and whatever I want to output with it"

显然,它只打印第一个标记。有没有办法让我在令牌上逐个打印,依次打印?

另外,%$data = $_.split(" "); Write-Output "$($data[0])" 部分是我从博客中得到的,我真的不明白我在做什么或语法是如何工作的。

我想用谷歌搜索它,但我不知道该怎么称呼它。请帮我说一两个词给 Google,或者一个链接向我解释 % 和所有 $ 符号的作用,以及左括号和右括号的意义。

我意识到我实际上不能使用(cat someFileInsteadOfAPipe).split(" "),因为文件(或最好的传入管道)包含多行。

关于一些答案:

如果您在标记化之前使用Select-String 过滤输出,您需要记住Select-String 命令的输出不是字符串集合,而是MatchInfo 对象的集合。要获取要拆分的字符串,您需要访问MatchInfo 对象的Line 属性,如下所示:

cat someFile | Select-String "keywordFoo" | %$_.Line.Split(" ")

【问题讨论】:

【参考方案1】:
"Once upon a time there were three little pigs".Split(" ") | ForEach 
    "$_ is a token"
 

key是$_,代表管道中的当前变量。

关于你在网上找到的代码:

%ForEach-Object 的别名。括号内的任何内容都会针对它接收到的每个对象运行一次。在这种情况下,它只运行一次,因为您要向它发送一个字符串。

$_.Split(" ") 正在获取当前变量并将其拆分为空格。当前变量将是 ForEach 当前正在循环的任何内容。

【讨论】:

啊啊,感谢您的编辑。知道 %foreach-object 的缩写意味着我可以对多行​​执行此操作:cat .\tmp.txt | %$_.Split(" ") | %Write-Output "$($_) hello" 问题已解决。 完美!很高兴我能帮助你。您的命令的最后一部分实际上可能只是"$_ hello"。如果您尝试在字符串中扩展对象属性的值,则只需要使用 $($variable) 表示法。例如"My last name is $($person.surname)." 或 cmdlet 方法的输出:"Tomorrow's date is $((Get-Date).AddDays(1))" 请注意:从 PowerShell v2 开始,有一个 -split 运算符可用于在一般空格 (-split $foo) 上拆分,或类似于 .Split(' '): $foo -split ' '【参考方案2】:

补充Justus Thane's helpful answer:

正如Joey 在评论中指出的那样,PowerShell 有一个强大的、基于正则表达式的-split operator

在其 一元 形式 (-split '...') 中,-split 的行为类似于 awk 的默认字段拆分,这意味着: 忽略前导和尾随空格。 任何运行个空格(例如,多个相邻空格)都被视为单个分隔符。

PowerShell v4+ 中,可以使用基于表达式的 - 因此更快 - ForEach-Object 的替代品cmdlet.ForEach() 数组(collection) 方法,如this blog post 中所述(与.Where() 方法一起,是Where-Object 的更强大、基于表达式的替代方法)。

以下是基于这些功能的解决方案:

PS> (-split '   One      for the money   ').ForEach( "token: [$_]" )
token: [One]
token: [for]
token: [the]
token: [money]

请注意,前导和尾随空格被忽略,Onefor 之间的多个空格被视为单个分隔符。

【讨论】:

【参考方案3】:

-split 输出一个数组,你可以像这样将它保存到一个变量中:

$a = -split 'Once  upon    a     time'
$a[0]

Once

另一个可爱的东西,你可以在赋值语句的两边都有数组:

$a,$b,$c = -split 'Once  upon    a'
$c

a

【讨论】:

【参考方案4】:

实现此目的的另一种方法是结合 Justus Thane 和 mklement0 的答案。当您查看单行示例时,这样做没有意义,但是当您尝试批量编辑文件或一堆文件名时,它非常方便:

$test = '   One      for the money   '
$option = [System.StringSplitOptions]::RemoveEmptyEntries
$($test.split(' ',$option)).foreach$_

结果如下:

One
for
the
money

【讨论】:

我一直发现在使用纯文本文件时,我得到了错误的数字,其中一行包含一个计算机名称(主机名)和一个空行。 $counterTotal = $($computers.Split(" ").count) 正是我想要的。感谢@s31064 的启发

以上是关于使用 PowerShell 拆分字符串并对每个令牌执行一些操作的主要内容,如果未能解决你的问题,请参考以下文章

当内容在单引号中时,使用 PowerShell 将 SQL 文件/字符串拆分为批处理排除拆分

将 pandas df 中的句子拆分为多行单词并对每个句子进行编号

如何将字符串拆分为列表并在python中将两个已知令牌合并为一个?

想要一种使用 PowerShell 将不同字符串拆分为多个部分的通用方法

(18)Powershell中的字符串拆分运算符

C ++拆分字符串基于/使用(增强)正则表达式来查找令牌