[英]Why PowerShell -Replace is adding an extra white space in front of each line?
[英]Why + operator adding space in powershell
我遇到奇怪的问题。 我有一个文件,内容如下
-----MyData-----
aaa
bbb
ccc
ddd
-----YourData-----
我写了一个 function 来在一个字符串中获取文件的所有数据,除了第一行和最后一行。 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
}
现在,此方法按预期返回“ aaabbbcccddd ”,但在 IF 块中,如果我使用 $returningData+$line 而不是我现在使用的 write 那么它返回“ aaa bbb ccc ddd ”。
我寻找它,但找不到任何答案。 为什么简单的串联添加一个额外的空间?
这里有两件事在起作用:
PowerShell 将对象(包括数组)显示和/或转换为字符串的方式:
$MyData = 'aaa', 'bbb', 'ccc', 'ddd'
PS C:\> "$MyData"
aaa bbb ccc ddd
PS C:\> Write-Host $MyData
aaa bbb ccc ddd
或来自管道的 output(展开):
PS C:\> $MyData # Simular to: $MyData | ForEach-Object { $_ }
aaa
bbb
ccc
ddd
另请注意,arrays 在字符串或 output 中被展平(参见例如:为什么 PowerShell 会自动展平 ZA3DCBC53F9D0CE672FE71? )
为了更好地显示 object 及其结构,您可以考虑使用序列化程序,例如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'
这里发挥的另一件事是自动类型转换,其中对象在用作运算符的操作数时被隐式转换为相同的类型。 这意味着如果操作数的类型不同,则第一个操作数的类型将用于操作,第二个操作数将转换为与第一个操作数相同的类型(如果可能)。
这对比较运算符很重要:
PS C:\> 10 -gt '9' # 10 > 9
True
PS C:\> '10' -gt 9 # '10' < '9'
False
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 = ''
在这件事上可能会给你不同的结果。
注意:与使用增加赋值运算符 ( +=
) 创建 object 集合一样,您通常应该避免使用增加赋值运算符 ( +=
) 来构建字符串,因为它是指数级的昂贵。
相反,我建议您使用管道和-Join
运算符来构建字符串:
PS C:\> $MyData -Join ''
aaabbbcccddd
或在您的脚本中:
$returningData = @(
foreach($line in $MyData) {
if(-not ($line -like '*a*') -and -not ($line -like '*b*')){ $line }
}
) -Join ''
@iron 的答案有很多很好的信息,但我们不要忽视 PowerShell 的简洁程度。 我设法将其简化为几行:
$File = 'C:\temp\MyData.txt'
$Patterns = @('.-MyData-.','.-YourData-.','^$')
$String = (Select-String -Pattern $Patterns -Path $File -NotMatch ).line -join ''
假设用例与问题所示的一样简单。
我还要指出,如果其他评论是正确的并且某处有胭脂空间。 你可以 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()
只会在行首和行尾占用空格。 如果要删除每行的所有空格,可以按照评论之一的建议使用.Replace( ' ', '' )
。
我敢肯定我的 RegEx 可能会好一点,但我得走了,如果有人有一些指示,请编辑或添加到评论中。 谢谢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.