使用Get-Content
从文件中删除空格时:
$file = "C:\Folder\MyFile001.txt"
Get-Content -Path $file | ? { -not [string]::IsNullOrWhiteSpace($_) } | Set-Content -Path $file
显示错误消息'Set-Content:该进程无法访问文件'...',因为它正在被另一个进程使用。
解决方法是在Get-Content
中使用括号:
(Get-Content -Path $file) | ...
这是什么原因?我想了解括号的区别,以及这是否适用于其他cmdlet。
答案 0 :(得分:4)
当cmdlet在管道上输出某些内容时,将在处理cmdlet的下一个输出之前执行管道。因此,当您的字符串沿流向Set-Content
的管道进行操作时,Get-Content
仍处于活动状态(输出文件处于打开状态),等待其继续执行。但是,当将表达式包装在()
中时,所有输出都将收集到一个数组中,然后将其向下推入管道。 Get-Content
完成并关闭文件。为了演示,请考虑以下功能:
function get-10dates { $count = 0; while($count -lt 10){ get-date; $count += 1 }}
在运行它并将其通过管道传递到foreach
循环时:
get-10dates | foreach { $_; sleep -Seconds 1 }
您将得到以下输出,由于foreach中的sleep
,每个日期都延迟了一秒钟:
# ~> get-10dates | foreach { $_; sleep -Seconds 1 }
June 19, 2019 9:58:36 AM
June 19, 2019 9:58:37 AM
June 19, 2019 9:58:38 AM
June 19, 2019 9:58:39 AM
June 19, 2019 9:58:40 AM
June 19, 2019 9:58:41 AM
June 19, 2019 9:58:42 AM
June 19, 2019 9:58:43 AM
June 19, 2019 9:58:44 AM
June 19, 2019 9:58:45 AM
现在,如果将函数包装在()
中。您会看到所有10个日期都在一次传递到管道之前立即创建(在1秒内):
# ~> (get-10dates) | foreach { $_; sleep -Seconds 1 }
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
答案 1 :(得分:0)
括号在Powershell中的工作方式与在代数中一样。
种类。
PowerShell首先在括号中执行该命令,然后尝试将其与要运行的位置进行类型匹配。在这种情况下,您要告诉它完成Get-Content的运行并将缓冲区读入内存,然后再继续执行下一个命令,而不是通过管道流式传输所有内容。
这与BaSH的工作方式类似,在其中您使用类似的内容(假设“ service.txt”包含一行写着apache的行):
Service $(cat /etc/service.txt) Stop
>> Service apache stop
将在$()中执行命令,并在运行其余命令之前将其作为文本返回。
在PowerShell中,您可以使用括号的类型匹配功能执行整洁的操作,例如使其仅返回单个对象属性:
(Get-ChildItem -filter "*.pdf" -Path .\Projects).FullName
>> C:\Users\ncf\Projects\Documentation.pdf