Какой метод по умолчанию вызывается для объекта с помощью Write-Output в Powershell? - PullRequest
4 голосов
/ 03 декабря 2010

Я обнаружил странное поведение с использованием powershell.

Вывод одного объекта в кавычках отличается от вывода метода ToString (), вызванного для того же объекта.

метод или свойство, вызванное в

Write-Output "$a"

Это каталог, который я запускаю, пример

> PS C:\temp\testps> DIR


    Directory: C:\temp\testps


Mode                LastWriteTime     Length Name                                       
----                -------------     ------ ----                                       
-a---        03/12/2010     11.21          8 1.txt                                      
-a---        03/12/2010     11.21          8 2.txt                                      
-a---        03/12/2010     11.21          8 3.txt                                      

Здесь я назначаю коллекцию файлов для объекта $ q

PS C:\temp\testps> $q  = Get-ChildItem . "*.txt"

Теперь я хочу напечатать имена файлов, но получаю неожиданный вывод

PS C:\temp\testps> foreach ($a in $q) {Write-Output $a}


    Directory: C:\temp\testps


Mode                LastWriteTime     Length Name                                       
----                -------------     ------ ----                                       
-a---        03/12/2010     11.21          8 1.txt                                      
-a---        03/12/2010     11.21          8 2.txt                                      
-a---        03/12/2010     11.21          8 3.txt                                      

Размещение кавычек вокруг имени объекта показывает правильное поведение

PS C:\temp\testps> foreach ($a in $q) {Write-Output "$a"}
1.txt
2.txt
3.txt

Этовывод только для первого объекта.Похоже, весь вывод команды DIR до первого имени файла.Unparsed.

PS C:\temp\testps> foreach ($a in $q) {Write-Output $a;break}


    Directory: C:\temp\testps


Mode                LastWriteTime     Length Name                                       
----                -------------     ------ ----                                       
-a---        03/12/2010     11.21          8 1.txt                                      

Метод ToString () ведет себя как объект в кавычках.

PS C:\temp\testps> foreach ($a in $q) {Write-Output $a.ToString()}
1.txt
2.txt
3.txt

Ответы [ 2 ]

5 голосов
/ 03 декабря 2010

Write-Output - это на самом деле просто явный способ отправить объект, который вы даете, следующей команде в pipleine.Поскольку вы не захватываете выходные данные, PowerShell использует форматирование по умолчанию для объекта.Это связано с тем, что Write-Output на самом деле не отправляет строку в stdout, а возвращает объект в конвейер.Объект в первом случае представляет собой массив объектов FileSystemInfo.

Когда вы возвращаете массив в PowerShell без захвата выходных данных, PowerShell пытается выполнить итерацию по массиву и использовать свою спецификацию форматирования по умолчанию для отображения каждого объекта в виде текста на stdout.

Итак, по порядкупредоставленных вами примеров, начиная с dir:

  1. dir, возвращает System.Array [System.IO.FileSystemInfo].Поскольку массив не захватывается никаким кодом, PowerShell использует формат по умолчанию для FileSystemInfo для отображения содержимого массива.

  2. происходит то же самое, что и выше, но именно вы выполняетеитерация.Вы фактически записываете свой собственный массив обратно в конвейер, восстанавливая тот же объект, который был возвращен get-childitem в первую очередь.Поскольку, опять же, ни один код не захватывает объект выходного массива, PowerShell отображает его так же, как и в первом случае.Это как если бы вы написали:

    PS C:\temp\testps> $q  = Get-ChildItem . "*.txt"
    PS C:\temp\testps> $children = foreach ($a in $q) {Write-Output $a}
    PS C:\temp\testps> $children
    

    Надеюсь, это проясняет, что ваш пример функционально эквивалентен вашему первому примеру.

  3. Здесь вы конвертируете каждыйОбъект в массиве в строку, поместив его в кавычки (что говорит PowerShell, чтобы вызвать $a.tostring()), прежде чем возвращать массив результатов.Итак, на этот раз вы возвращаете массив строк в конвейер.Поскольку вы не захватываете этот массив, PowerShell выполняет вывод текста на консоль по умолчанию, который в случае строки является просто текстом строки.

  4. Это аналогичнов случаях 1 и 2, в которых PowerShell использует свой выходной формат по умолчанию для объекта FileSystemInfo.

  5. Это аналогично 3, поскольку вы снова возвращаете массив строк.Единственное отличие заключается в семантике ... вы вызываете ToString() явно, а не неявно, как, например, когда вы помещаете объект в кавычки.

Для получения дополнительной информации о форматировании по умолчанию см. help about_format

5 голосов
/ 03 декабря 2010

В первом случае Write-Output $a объект (System.IO.FileInfo) форматируется механизмом форматирования PowerShell на основе данных форматирования, хранящихся в $pshome\FileSystem.format.ps1xml. То есть, что действительно выполняется:

Write-Output $a | Out-Default

Out-Default неявно выполняется в конце конвейера, и именно командлет выполняет форматирование на основе данных форматирования.

В случае "$a" используется представление ToString().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...