Как добавить новую строку в вывод команды в PowerShell? - PullRequest
65 голосов
/ 28 октября 2009

Я запускаю следующий код, используя PowerShell, чтобы получить список добавления / удаления программ из реестра:

Get-ChildItem -path hklm:\software\microsoft\windows\currentversion\uninstall `
    | ForEach-Object -Process { Write-Output $_.GetValue("DisplayName") } `
    | Out-File addrem.txt

Я хочу, чтобы список был разделен символами новой строки для каждой программы. Я пробовал:

Get-ChildItem -path hklm:\software\microsoft\windows\currentversion\uninstall `
    | ForEach-Object -Process { Write-Output $_.GetValue("DisplayName") `n } `
    | out-file test.txt

Get-ChildItem -path hklm:\software\microsoft\windows\currentversion\uninstall `
    | ForEach-Object {$_.GetValue("DisplayName") } `
    | Write-Host -Separator `n

Get-ChildItem -path hklm:\software\microsoft\windows\currentversion\uninstall `
    | ForEach-Object -Process { $_.GetValue("DisplayName") } `
    | foreach($_) { echo $_ `n }

Но все это приводит к странному форматированию при выводе на консоль и с тремя квадратными символами после каждой строки при выводе в файл. Я попытался Format-List, Format-Table и Format-Wide без удачи. Первоначально я думал, что-то вроде этого будет работать:

Get-ChildItem -path hklm:\software\microsoft\windows\currentversion\uninstall `
    | ForEach-Object -Process { "$_.GetValue("DisplayName") `n" }

Но это только что дало мне ошибку.

Ответы [ 5 ]

84 голосов
/ 29 октября 2009

Или просто установите разделитель выходного поля (OFS), чтобы удвоить символы новой строки, а затем убедитесь, что вы получаете строку при отправке ее в файл:

$OFS = "`r`n`r`n"
"$( gci -path hklm:\software\microsoft\windows\currentversion\uninstall | 
    ForEach-Object -Process { write-output $_.GetValue('DisplayName') } )" | 
 out-file addrem.txt

Остерегайтесь использовать `, а не '. На моей клавиатуре (англо-американская раскладка Qwerty) она расположена слева от 1 .
(Перенесено сюда из комментариев - спасибо Коену Зомерсу)

73 голосов
/ 28 октября 2009

Попробуйте:

PS> $nl = [Environment]::NewLine
PS> gci hklm:\software\microsoft\windows\currentversion\uninstall | 
        ForEach { $_.GetValue("DisplayName") } | Where {$_} | Sort |
        Foreach {"$_$nl"} | Out-File addrem.txt -Enc ascii

В моем файле addrem.txt выдается следующий текст:

Adobe AIR

Adobe Flash Player 10 ActiveX

...

Примечание: в моей системе GetValue ("DisplayName") возвращает ноль для некоторых записей, поэтому я отфильтрую их. Кстати, вы были близки с этим:

ForEach-Object -Process { "$_.GetValue("DisplayName") `n" }

За исключением того, что внутри строки, если вам нужно получить доступ к свойству переменной, то есть «вычислить выражение», вам необходимо использовать синтаксис подвыражения, например:

Foreach-Object -Process { "$($_.GetValue('DisplayName'))`r`n" }

По существу, внутри строки в двойных кавычках PowerShell будет расширять переменные, такие как $_, но не будет оценивать выражения , если только вы не поместите выражение в подвыражение, используя следующий синтаксис:

$(`<Multiple statements can go in here`>).
6 голосов
/ 29 октября 2009

В конечном счете, то, что вы пытаетесь сделать с ДОПОЛНИТЕЛЬНЫМИ пустыми строками между каждой, немного сбивает с толку :)

Я думаю, вы действительно хотите использовать Get-ItemProperty . Вы получите ошибки, если значения отсутствуют, но вы можете подавить их с помощью -ErrorAction 0 или просто оставить их как напоминания. Поскольку поставщик реестра возвращает дополнительные свойства, вам нужно вставить Select-Object , который использует те же свойства, что и Get-Properties.

Затем, если вы хотите, чтобы каждое свойство находилось в строке с пустой строкой, используйте Format-List (в противном случае используйте Format-Table , чтобы получить по одному на строку).

gci -path hklm:\software\microsoft\windows\currentversion\uninstall |
gp -Name DisplayName, InstallDate | 
select DisplayName, InstallDate | 
fl | out-file addrem.txt
5 голосов
/ 29 октября 2009

Я думаю, у вас была правильная идея с вашим последним примером. Вы получили ошибку только потому, что пытались поместить кавычки в уже заключенную в кавычки строку. Это исправит это:

gci -path hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object -Process { write-output ($_.GetValue("DisplayName") + "`n") }

Редактировать: оператор Кита () фактически создает лучший синтаксис (я всегда забываю об этом). Вы также можете экранировать кавычки внутри кавычек следующим образом:

gci -path hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object -Process { write-output "$($_.GetValue(`"DisplayName`"))`n" }
4 голосов
/ 21 февраля 2013

Опция, которую я склонен использовать, в основном потому, что она проста и мне не нужно думать, использует Write-Output , как показано ниже. Write-Output поместит маркер EOL в строку для вас, и вы можете просто вывести готовую строку.

Write-Output $stringThatNeedsEOLMarker | Out-File -FilePath PathToFile -Append

В качестве альтернативы, вы также можете просто построить всю строку, используя Write-Output, а затем вставить готовую строку в Out-File .

...