简体   繁体   English

为什么 + 运算符在 powershell 中添加空格

[英]Why + operator adding space in powershell

I encounter strange issue.我遇到奇怪的问题。 I have a file with content like我有一个文件,内容如下

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

and I wrote a function to get all data of file in a single string except first and last line.我写了一个 function 来在一个字符串中获取文件的所有数据,除了第一行和最后一行。 The function is as follows function如下

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
}

Now, this method is returning " aaabbbcccddd " as expected but in IF block if I use $returningData+$line instead of what I am using write now then it returns " aaa bbb ccc ddd ".现在,此方法按预期返回“ aaabbbcccddd ”,但在 IF 块中,如果我使用 $returningData+$line 而不是我现在使用的 write 那么它返回“ aaa bbb ccc ddd ”。

I looked for it but couldn't find any answer.我寻找它,但找不到任何答案。 Why simple concatenation adding an extra space?为什么简单的串联添加一个额外的空间?

There are two things in play here:这里有两件事在起作用:

Displaying data显示数据

The way PowerShell displays and/or converts objects (including arrays) into a string: PowerShell 将对象(包括数组)显示和/或转换为字符串的方式:

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

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

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

Or output (unroll) from the pipeline:或来自管道的 output(展开):

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

Also be aware that the arrays are flattened in a string or output (see eg: Why does PowerShell flatten arrays automatically? )另请注意,arrays 在字符串或 output 中被展平(参见例如:为什么 PowerShell 会自动展平 ZA3DCBC53F9D0CE672FE71?

To better display the object and its structure, you might consider to use an serializer , like ConvertTo-Json :为了更好地显示 object 及其结构,您可以考虑使用序列化程序,例如ConvertTo-Json

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

Or ConvertTo-Expression for even more complex objects like: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类型铸造

The other thing in play here is the automatic type casting where objects are implicitly converted to the same type when used as operands with an operator.这里发挥的另一件事是自动类型转换,其中对象在用作运算符的操作数时被隐式转换为相同的类型。 Meaning if the operands are of a different type, the type of the first operand will be used for the operation and the second operand will be converted to the same type (if possible) as the first one.这意味着如果操作数的类型不同,则第一个操作数的类型将用于操作,第二个操作数将转换为与第一个操作数相同的类型(如果可能)。

This counts for comparison operators :这对比较运算符很重要:

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

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

And most other operators including arithmetic operators :和大多数其他运算符,包括算术运算符

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

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

And also in case of an array :而且在数组的情况下

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

In case the first operand is $Null (which isn't part of any data type), the type of the second operand is used:如果第一个操作数是$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

Conclusion结论

Changing your line:改变你的线路:

$returningData = $null

to:至:

$returningData = @()

or:或者:

$returningData = ''

Will likely give you different results in this matter.在这件事上可能会给你不同的结果。

Note: as with using the increase assignment operator ( += ) to create an object collection , you should generally avoid using the increase assignment operator ( += ) for building strings as it is exponential expensive.注意:使用增加赋值运算符 ( += ) 创建 object 集合一样,您通常应该避免使用增加赋值运算符 ( += ) 来构建字符串,因为它是指数级的昂贵。

Instead, I recommend you to use the pipeline and the -Join operator for building strings:相反,我建议您使用管道和-Join运算符来构建字符串:

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

Or in your script:或在您的脚本中:

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

@iron's answer has a lot of great information, but let's not ignore how concise PowerShell can be. @iron 的答案有很多很好的信息,但我们不要忽视 PowerShell 的简洁程度。 I managed to bring this down to a few lines:我设法将其简化为几行:

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

Assuming the use case is as simple as the question indicates.假设用例与问题所示的一样简单。

I'd also point out that if other comments are correct and there are rouge spaces somewhere.我还要指出,如果其他评论是正确的并且某处有胭脂空间。 you could pipe this to ForEach-Object to trim each line.你可以 pipe 这个到ForEach-Object来修剪每一行。

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

.Trim() will only take spaces from the beginning and end of the line. .Trim()只会在行首和行尾占用空格。 you can use .Replace( ' ', '' ) as suggested by one of the comments if you want to remove all spaces per line.如果要删除每行的所有空格,可以按照评论之一的建议使用.Replace( ' ', '' )

I'm sure my RegEx's could be a little better, but I gotta head out, if any one has some pointers, either edit or add to the comments.我敢肯定我的 RegEx 可能会好一点,但我得走了,如果有人有一些指示,请编辑或添加到评论中。 Thanks.谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM