Когда PowerShell интерпретирует вывод из внешних программ (например, ytd
в вашем случае), предполагает, что в выводе используется кодировка символов, отраженная в [Console]::OutputEncoding
.
Примечание:
Интерпретация относится к случаям, когда PowerShell захватывает (например, $output = ...
), реле (например, ... | Select-String ...
) или перенаправляет (например, ... > output.txt
) на выход внешней программы.
Напротив, печатая напрямуюна дисплей это не влияет, поскольку PowerShell не задействован (что объясняет, почему символы выглядели так, как ожидалось в вашей консоли, когда вывод ytd
выводился непосредственно на нее).
Если кодировка, сообщаемая [Console]::OutputEncoding
, не совпадает с кодировкой, используемой внешней программой, PowerShell неверно интерпретирует вывод.
Чтобы это исправить, необходимо(временно) установите [Console]::OutputEncoding]
в соответствии с кодировкой, используемой внешней программой .
Например,давайте предположим, что исполняемый файл foo.exe
выводит текст в кодировке UTF-8:
# Save the current encoding and switch to UTF-8.
$prev = [Console]::OutputEncoding
[Console]::OutputEncoding = [Text.Encoding]::Utf8
# PowerShell now interprets foo's output correctly as UTF-8-encoded.
# and $output will correctly contain CJK characters.
$output = foo https://example.org -e
# Restore the previous encoding.
[Console]::OutputEncoding = $prev
Важно :
Изменение[Console]::OutputEncoding
в соответствии с кодировкой символов внешней программы в настоящее время не работает в PowerShell Core , по состоянию на 7.0.0-preview.4 и , скорее всего, будут исправлены вv7.0 - см. отчет об ошибке на GitHub ; Windows PowerShell не изменяется.
[Console]::OutputEncoding
по умолчанию отражает кодировку, связанную с кодовой страницей OEM устаревшей языковой системы , о чем сообщает chcp
(например, 437
в системах на английском и американском языках).
Имея конкретную программу под рукой, youtube-dl
, js2010 обнаружил , что захватв переменной работает без лишних усилий, если вы передаете --encoding utf-16
.
. Причина, по которой это работает, заключается в том, что результирующий выход в кодировке UTF16-LE имеет значение , которому предшествует спецификация (метка порядка байтов).
(Обратите внимание, что --encoding utf-8
не не работает, потому что youtube-dl
затем не излучает спецификацию.)
Windows PowerShell способна обнаруживать и правильно декодировать текст в кодировке UTF-16LE и кодировке UTF-8 независимо от действующего [Console]::OutputEncoding]
ЕСЛИ И ТОЛЬКО ЕСЛИ выходу предшествуетспецификация
Предостережения :
Это не работает в PowerShell Core (на любом изподдерживаемые платформы)
Даже в Windows PowerShell вы редко сможете воспользоваться этим неясным поведением, поскольку использование спецификации в выводе stdout равно нетипичный (обычно используется только в файлах ).