【问题标题】:Why + operator adding space in powershell为什么 + 运算符在 powershell 中添加空间
【发布时间】:2020-07-03 16:08:15
【问题描述】:

我遇到了奇怪的问题。我有一个文件,内容类似于

-----MyData-----
aaa
bbb
ccc
ddd
-----YourData-----

我写了一个函数来获取文件的所有数据在一个字符串中,除了第一行和最后一行。函数如下

function readFile([string] $datapath){
$returningData = $null
foreach($line in [System.IO.File]::ReadLines($datapath)) {
    if(-not ($line -like '*-MyData-*') -and -not ($line -like '*-YourData-*')){
        $returningData+=$line
    }
}
return $returningData
}

现在,此方法按预期返回“aaabbbcccddd”,但在 IF 块中,如果我使用 $returningData+$line 而不是我现在使用的 write 那么它返回“aaa bbb ccc ddd”。

我寻找它,但找不到任何答案。为什么要简单的串联添加额外的空格?

【问题讨论】:

  • 根据数据格式,添加 return $returningData.ToString().Replace(" ","") 将删除所有空格。如果其中有依赖于空格的数据,则不起作用。除此之外:我尝试了您的脚本,将输入值复制到一个文件中,并且从未得到任何空格。使用“+”,它每行输出它,“+=”作为单行,但任何地方都没有空格,所以我认为你的输入文件中有一些空格。
  • 我同意@Bowshock 的观点,即您的问题并没有真正表明您正在处理的问题(如果您仍然可以将其添加到问题中,那就太好了)。另一方面,您正在处理的这个问题可能是由于一些常见的 PowerShell 陷阱造成的。

标签: powershell


【解决方案1】:

这里有两件事在起作用:

显示数据

PowerShell 显示和/或将对象(包括数组)转换为字符串的方式:

$MyData = 'aaa', 'bbb', 'ccc', 'ddd'

PS C:\> "$MyData"
aaa bbb ccc ddd

PS C:\> Write-Host $MyData
aaa bbb ccc ddd

或从管道输出(展开):

PS C:\> $MyData # Simular to: $MyData | ForEach-Object { $_ }
aaa
bbb
ccc
ddd

还要注意,数组在字符串或输出中被展平(参见例如:Why does PowerShell flatten arrays automatically?

为了更好地显示对象及其结构,您可以考虑使用serializer,例如ConvertTo-Json

PS C:\> ConvertTo-Json $MyData
[
  "aaa",
  "bbb",
  "ccc",
  "ddd"
]

ConvertTo-Expression 用于更复杂的对象,例如:

$MyObject = 'aaa', @([datetime]'1963-10-07', [version]'1.2.3'), 'bbb'

PS C:\> Write-Host $MyObject
aaa 10/7/1963 12:00:00 AM 1.2.3 bbb

PS C:\> ConvertTo-Expression $MyObject
'aaa',
(
        [datetime]'1963-10-07T00:00:00.0000000',
        [version]'1.2.3'
),
'bbb'

类型转换

这里起作用的另一件事是自动type casting,其中对象在用作运算符的操作数时被隐式转换为相同的类型。这意味着如果操作数的类型不同,则第一个操作数的类型将用于操作,第二个操作数将转换为与第一个操作数相同的类型(如果可能)。

这对 comparison operators 很重要:

PS C:\> 10 -gt '9' # 10 > 9
True

PS C:\> '10' -gt 9 # '10' < '9'
False

以及大多数其他operators,包括arithmetic operators

PS C:\> 10 + '9' # Results in a integer: 10 + 9
19

PS C:\> '10' + 9 # Results in a string: '10' + '9'
109

还有如果是数组

PS C:\> 'aaa' + 'bbb', 'ccc' # Results in a string: 'aaa' + 'bbb ccc'
aaabbb ccc

PS C:\> 'aaa', 'bbb' + 'ccc' # Results in an array: 'aaa', 'bbb' + @('ccc')
aaa
bbb
ccc

如果第一个操作数是$Null(不属于任何数据类型),则使用第二个操作数的类型:

PS C:\> $a = $Null + 'aaa'
PS C:\> $a.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

PS C:\> $a = $Null + @('aaa')
PS C:\> $a.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

结论

换行:

$returningData = $null

到:

$returningData = @()

或:

$returningData = ''

在这件事上可能会给你不同的结果。

注意:using the increase assignment operator (+=) to create an object collection 一样,您通常应避免使用递增赋值运算符 (+=) 来构建字符串,因为它的代价是指数级的。 p>

相反,我建议您使用管道和-Join 运算符来构建字符串:

PS C:\> $MyData -Join ''
aaabbbcccddd

或者在你的脚本中:

$returningData = @(
    foreach($line in $MyData) {
        if(-not ($line -like '*a*') -and -not ($line -like '*b*')){ $line }
    }
) -Join ''

【讨论】:

    【解决方案2】:

    @iron 的回答包含很多重要信息,但我们不要忽视 PowerShell 的简洁性。我设法将其简化为几行:

    $File = 'C:\temp\MyData.txt'
    $Patterns = @('.-MyData-.','.-YourData-.','^$')
    $String = (Select-String -Pattern $Patterns -Path $File -NotMatch ).line -join ''
    

    假设用例与问题所示的一样简单。

    我还要指出,如果其他 cmets 是正确的并且某处有胭脂空间。您可以将其通过管道发送到 ForEach-Object 以修剪每一行。

    $File = 'C:\temp\MyData.txt'
    $Patterns = @('.-MyData-.','.-YourData-.','^$')
    $String = ( (Select-String -Pattern $Patterns -Path $File -NotMatch ).line | ForEach-Object{ $_.Trim() } ) -join ''
    

    .Trim() 只会在行首和行尾占用空格。如果您想删除每行的所有空格,您可以按照其中一位 cmets 的建议使用 .Replace( ' ', '' )

    我确信我的 RegEx 可能会好一点,但我得走了,如果有人有一些指示,请编辑或添加到 cmets。谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 2018-06-23
      • 1970-01-01
      相关资源
      最近更新 更多