Powershell изменить кодировку файла

Обновлено: 07.07.2024

По умолчанию, когда вы перенаправляете вывод команды в файл или перенаправляете его во что-то другое в PowerShell, используется кодировка UTF-16, что бесполезно. Я хочу изменить его на UTF-8.

Это можно сделать в каждом конкретном случае, заменив >foo.txt синтаксис на, | out-file foo.txt -encoding utf8 но неудобно повторять каждый раз.

Постоянный способ настроить вещи в PowerShell - это вставить их \Users\me\Documents\WindowsPowerShell\profile.ps1 ; Я убедился, что этот файл действительно запускается при запуске.

Было сказано, что кодировка вывода может быть установлена, $PSDefaultParameterValues = @ но я пробовал это, и это не повлияло.

Как настроить PowerShell на использование UTF-8?

Примечание . Следующее относится к Windows PowerShell .
См. Следующий раздел для кросс-платформенной версии PowerShell Core (v6 +) .

В PSv5.1 или выше , где > и >> являются фактически псевдонимами Out-File , вы можете установить кодировку по умолчанию для > / >> / с Out-File помощью $PSDefaultParameterValues переменной предпочтений :

  • $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'

В PSv5.0 или ниже вы не можете изменить кодировку для > / >> , но в PSv3 или выше описанный выше метод действительно работает для явных вызовов Out-File .
( $PSDefaultParameterValues Переменная предпочтений была введена в PSv3.0).

На PSv3.0 или выше , если вы хотите установить по умолчанию кодировку для всех командлетов , которые поддерживают
в -Encoding параметр (который в PSv5.1 + включает в себя > и >> ), используйте:

Если вы поместите эту команду в свои $PROFILE командлеты, такие как Out-File и Set-Content , по умолчанию будут использовать кодировку UTF-8, но обратите внимание, что это делает ее глобальным параметром сеанса , который повлияет на все команды / сценарии, которые явно не указывают кодировку.

Точно так же не забудьте включить такие команды в свои сценарии или модули, которые вы хотите вести таким же образом , чтобы они действительно вели себя одинаково, даже когда их запускает другой пользователь или другая машина.

Предостережение : ** PowerShell, начиная с версии 5.1 , неизменно создает файлы UTF-8 _с (псевдо) спецификацией _ ** , что является обычным явлением только в мире Windows - утилиты на основе Unix не распознают эту спецификацию (см. Внизу); см. этот пост для обходных путей, которые создают файлы UTF-8 без спецификации.

Для резюме дико непоследовательного поведения кодирования символов по умолчанию во многих стандартных командлетов Windows PowerShell см нижнюю секцию.

Автоматическая $OutputEncoding переменная не связана и применяется только к тому, как PowerShell взаимодействует с внешними программами (какую кодировку использует PowerShell при отправке им строк) - она ​​не имеет ничего общего с кодировкой, которую операторы перенаправления вывода и командлеты PowerShell используют для сохранения в файлы.

Дополнительное чтение: кроссплатформенная перспектива: PowerShell Core :

PowerShell теперь является кроссплатформенным , благодаря своей редакции PowerShell Core , чья кодировка - разумно - по умолчанию использует UTF-8 без спецификации , что соответствует Unix-подобным платформам.

Это означает , что исходный код-файлы без спецификации предполагается UTF-8, и с помощью > / Out-File / по Set-Content умолчанию в спецификацию менее UTF-8; явное использование utf8 -Encoding аргумента также создает UTF-8 без спецификации , но вы можете выбрать создание файлов с псевдо-спецификацией со utf8bom значением.

Если вы создаете сценарии PowerShell с помощью редактора на Unix-подобной платформе, а в настоящее время даже в Windows с кросс-платформенными редакторами, такими как Visual Studio Code и Sublime Text, полученный *.ps1 файл обычно не будет иметь псевдо-спецификации UTF-8:

  • Это отлично работает в PowerShell Core .
  • Он может сломаться в Windows PowerShell , если файл содержит символы, отличные от ASCII; если вам действительно нужно использовать символы, отличные от ASCII, в ваших скриптах, сохраните их как UTF-8 с BOM .
    Без спецификации Windows PowerShell (неверно) интерпретирует ваш сценарий как закодированный в устаревшей кодовой странице «ANSI» (определяемой языковым стандартом системы для приложений, предшествующих Unicode; например, Windows-1252 в системах на английском языке).

С другой стороны , файлы , которые делают имеют UTF-8 псевдо-BOM может быть проблематичным , на Unix-подобных платформах, так как они вызывают Unix утилит , таких как cat , sed и awk - и даже некоторые редакторы , такие как gedit - чтобы передать псевдо-BOM через , т.е. рассматривать это как данные .

  • Это не всегда может быть проблемой, но определенно может быть, например, когда вы пытаетесь прочитать файл в строке bash , скажем, text=$(cat file) или text=$(<file) - результирующая переменная будет содержать псевдо-спецификацию в качестве первых 3 байтов.

Несогласованное поведение кодировки по умолчанию в Windows PowerShell :

К сожалению, кодировка символов по умолчанию, используемая в Windows PowerShell, очень непоследовательна; Кросс-платформенная версия PowerShell Core , как обсуждалось в предыдущем разделе, похвально положила этому конец.

Нижеследующее не претендует на охват всех стандартных командлетов.

Поиск в Google имен командлетов для поиска их тем справки теперь по умолчанию показывает версию тем PowerShell Core ; используйте раскрывающийся список версий над списком тем слева, чтобы переключиться на версию Windows PowerShell .

На момент написания этой статьи в документации часто неверно утверждается, что ASCII является кодировкой по умолчанию в Windows PowerShell - см. Эту проблему с документацией GitHub .

Командлеты, которые пишут :

Out-File и > / >> создать "Unicode" - UTF-16LE - файлы по умолчанию - в которых каждый символ диапазона ASCII (тоже) представлен двумя байтами, что заметно отличается от Set-Content / Add-Content (см. следующий пункт); New-ModuleManifest а Export-CliXml также создавать файлы UTF-16LE.

Set-Content (и Add-Content если файл еще не существует / пуст) использует кодировку ANSI (кодировку, заданную устаревшей кодовой страницей ANSI активного языкового стандарта, которую вызывает PowerShell Default ).

Export-Csv действительно создает файлы ASCII, как -Append описано в документации, но см. примечания ниже.

Export-PSSession по умолчанию создает файлы UTF-8 с спецификацией.

New-Item -Type File -Value в настоящее время создает UTF-8 без спецификации (!).

В Send-MailMessage разделе справки также утверждается, что по умолчанию используется кодировка ASCII - я лично не проверял это утверждение.

Start-Transcript неизменно создает файлы UTF-8 с BOM, но см. примечания -Append ниже.

Re команды, которые добавляются в существующий файл:

>> / Out-File -Append Не делать не попытки соответствовать кодировке файла существующего контента . То есть они вслепую применяют свою кодировку по умолчанию, если не указано иное -Encoding , что невозможно >> (за исключением косвенного в PSv5.1 +, через $PSDefaultParameterValues , как показано выше). Вкратце: вы должны знать кодировку содержимого существующего файла и добавлять его, используя ту же кодировку.

Add-Content является похвальным исключением: при отсутствии явного -Encoding аргумента он обнаруживает существующую кодировку и автоматически применяет ее к новому контенту. Спасибо, js2010 . Обратите внимание, что в Windows PowerShell это означает, что применяется кодировка ANSI, если существующее содержимое не имеет спецификации, тогда как в PowerShell Core используется кодировка UTF-8.

Это несоответствие между Out-File -Append / >> и Add-Content , которое также влияет на PowerShell Core , обсуждается в этом выпуске GitHub .

Export-Csv -Append частично соответствует существующей кодировке: он слепо добавляет UTF-8, если кодировка существующего файла является любой из ASCII / UTF-8 / ANSI, но правильно соответствует UTF-16LE и UTF-16BE.
Другими словами: при отсутствии спецификации Export-Csv -Append предполагается , что используется UTF-8, тогда как Add-Content предполагается, что ANSI.

Start-Transcript -Append частично соответствует существующей кодировке: она правильно соответствует кодировкам с BOM , но по умолчанию используется кодировка ASCII с потенциально потерями при ее отсутствии.

Командлеты, которые читают (то есть кодировку, используемую при отсутствии спецификации ):

Get-Content и по Import-PowerShellDataFile умолчанию используется ANSI ( Default ), что согласуется с Set-Content .
ANSI - это также то, что по умолчанию использует сам движок PowerShell при чтении исходного кода из файлов.

В отличие от этого Import-Csv , Import-CliXml и Select-String предположим , UTF-8 в отсутствие спецификации.

При использовании VS Code для создания и редактирования сценариев PowerShell очень важно, чтобы ваши файлы сохранялись в правильной кодировке символов.

Что такое кодировка и почему она важна?

VS Code управляет интерфейсом ввода строки символов в буфер пользователем и чтения-записи блоков байтов в файловой системе. При сохранении файла в VS Code используется кодирование текста для определения того, какие байты получит каждый символ. Подробные сведения см. в статье О шифровании символов.

Аналогичным образом, когда оболочка PowerShell запускает скрипт, ей необходимо преобразовать байты из файла в символы для преобразования файла в программу PowerShell. Так как VS Code записывает файл, а PowerShell считывает файл, этим средствам необходимо использовать одну и ту же систему кодировки. Этот процесс синтаксического анализа скрипта PowerShell идет так: байты -> символы -> лексемы -> дерево абстрактного синтаксиса -> выполнение.

И VS Code, и PowerShell устанавливаются с подходящей конфигурацией кодировки по умолчанию. Тем не менее кодировка по умолчанию, используемая PowerShell, была изменена с выпуском PowerShell 6. Чтобы избежать проблем с PowerShell и расширениями PowerShell в VS Code, необходимо настроить параметры VS Code и PowerShell должным образом.

Распространенные причины проблемы с кодировкой

Проблемы с кодировкой возникают, если кодировка VS Code в целом или вашего файла скрипта не совпадает с кодировкой, ожидаемой в PowerShell. В PowerShell нет способа автоматически определить кодировку файла.

Проблемы с кодировкой более вероятны при использовании символов не из 7-разрядной кодировки ASCII. Пример:

  • Расширенные небуквенные символы, такие как длинное тире ( — ), неразрывный пробел ( ) или левая двойная кавычка ( " ).
  • Латинские символы с диакритикой ( É , ü )
  • Нелатинские символы, такие как кириллица ( Д , Ц )
  • Символы иероглифического письма ( 本 , 화 , が ).

Распространенные причины проблем с кодировкой:

  • Параметры кодировок по умолчанию VS Code и PowerShell не были изменены. В версиях до PowerShell 5.1 (включительно) кодировка по умолчанию отличается от используемой в VS Code.
  • Открыт другой редактор, и файл перезаписан в новой кодировке. Это часто происходит с интегрированной средой сценариев.
  • Файл возвращается в систему управления версиями в кодировке, отличающейся от той, которая ожидается в VS Code или PowerShell. Это может произойти, когда участники совместной работы используют редакторы с различными конфигурациями кодировок.

Как определить наличие проблемы с кодировкой

Часто ошибки кодирования в скриптах представляются как ошибки синтаксического анализа. Если вы видите странные последовательности символов в скрипте, это может быть проблемой. В примере ниже тире ( – ) отображается в виде символов â&euro;" :

Эта проблема возникает, так как VS Code кодирует символ – в UTF-8 как байты 0xE2 0x80 0x93 . Если эти байты декодируются в кодировке Windows-1252, они интерпретируются как символы â&euro;" .

Некоторые странные последовательности символов, которые можно видеть:

  • â&euro;" вместо – .
  • â&euro;" вместо — .
  • Ä2 вместо Ä .
  • Â вместо (неразрывный пробел);
  • Ã&copy; вместо é .

Этот удобный справочник перечисляет распространенные шаблоны, которые указывают на проблему между кодировками UTF-8 и Windows-1252.

Взаимодействие расширения PowerShell для VS Code с кодировками

Расширение PowerShell взаимодействует со скриптами несколькими способами:

  1. При изменении скриптов в VS Code содержимое отправляется из VS Code в расширение. Протокол языкового сервера требует, чтобы это содержимое передавалось в UTF-8. Таким образом, расширение не сможет получить неправильную кодировку.
  2. При выполнении скриптов в интегрированной консоли они считываются оболочкой PowerShell непосредственно из файла. Если кодировка PowerShell отличается от кодировки VS Code, может произойти сбой.
  3. Когда скрипт, который открыт в VS Code, ссылается на другой скрипт, который не был открыт в VS Code, расширение загружает содержимое второго скрипта из файловой системы. Расширение PowerShell по умолчанию использует кодировку UTF-8, но при этом применяет обнаружение метки порядка байтов (BOM), чтобы выбрать правильную кодировку.

Проблема возникает при предположении кодировки, не использующей BOM (такой как UTF-8 без метки порядка байтов или Windows-1252). Расширение PowerShell по умолчанию использует UTF-8. Расширение не может изменить параметры кодировки в VS Code. Дополнительные сведения см. в разделе Проблема № 824.

Выбор подходящей кодировки

Различные системы и приложения могут использовать различные кодировки:

Кодировки Юникода также используют понятие метки порядка следования байтов (BOM). BOM ставится в начале текста, чтобы декодер мог определить, какая кодировка используется в тексте. Для многобайтовых кодировок BOM также указывает порядок следования байтов кодировки. BOM представляются байтами, которые редко встречаются в тексте в Юникоде. Это позволяет сделать обоснованное предположение, что текст записан в Юникоде, если присутствует метка BOM.

BOM не являются обязательными; в мире Linux они не так популярны, поскольку во всех прочих местах используется надежное соглашение UTF-8. Большинство приложений Linux предполагают, что текстовый ввод кодируется в UTF-8. Хотя многие приложения Linux могут распознавать и правильно обрабатывать BOM, некоторые этого не делают, что приводит к появлению артефактов в тексте, открываемом с помощью этих приложений.

Таким образом:

  • Если вы работаете в основном с приложениями Windows и Windows PowerShell, следует предпочтительно использовать такие кодировки, как UTF-8 с BOM или UTF-16.
  • Если вы работаете на разных платформах, следует отдавать предпочтение UTF-8 с BOM.
  • Если вы работаете главным образом в контексте Linux, следует отдавать предпочтение UTF-8 без BOM.
  • Windows-1252 и latin-1 — устаревшие кодировки, которых по возможности следует избегать. Тем не менее некоторые приложения предыдущих версий в Windows зависят от их.
  • Также стоит отметить, что подписывание скриптов зависит от кодировки, то есть изменение кодировки в подписанном скрипте потребует повторного подписывания.

Настройка VS Code

Кодировка VS Code по умолчанию — UTF-8 без метки порядка байтов.

Чтобы задать Кодировка в VS Code, перейдите к параметрам VS Code ( CTRL + , ) и задайте параметр "files.encoding" :

Возможны следующие значения:

  • utf8 : [UTF-8] без метки порядка байтов
  • utf8bom : [UTF-8] с меткой порядка байтов
  • utf16le : [UTF-16] с прямым порядком байтов
  • utf16be : [UTF-16] с обратным порядком байтов
  • windows1252 : [Windows-1252]

Должен отобразиться раскрывающийся список представления графического пользовательского интерфейса или дополнение в представлении JSON.

Чтобы обеспечить автоматическое определение кодировки, если это возможно, можно также добавить следующее:

Если вы не хотите, чтобы эти параметры влияли на все типы файлов, в VS Code можно задавать конфигурации для каждого языка отдельно. Создать параметр для конкретного языка можно, поместив параметры в поле [<language-name>] . Пример:

Вы также можете установить средство отслеживания Gremlins для Visual Studio Code. Это расширение раскрывает определенные символы Юникода, которые могут быть легко повреждены из-за своей невидимости или схожести с другими обычными символами.

Настройка PowerShell

В PowerShell кодировка по умолчанию зависит от версии:

  • В PowerShell 6+ кодировка по умолчанию на всех платформах — UTF-8 без метки порядка байтов.
  • В Windows PowerShell кодировка по умолчанию — обычно Windows-1252, расширение latin-1, которое также называется ISO 8859-1.

В PowerShell 5 + можно определить кодировку по умолчанию так:

Следующий скрипт может использоваться для определения кодировки, которую ваш сеанс PowerShell выводит для скрипта, где нет метки порядка байтов.

Можно настроить PowerShell так, чтобы использовать заданную кодировку в более общем виде с помощью параметров профиля. См. следующие статьи:

Заставить PowerShell использовать конкретную кодировку для входных данных невозможно. В PowerShell 5.1 и более ранних версий в Windows с языковым стандартом en-US по умолчанию используется кодировка Windows-1252, если отсутствует метка порядка байтов. Другие параметры языкового стандарта могут использовать другую кодировку. Для обеспечения совместимости лучше сохранять скрипты в Юникоде с меткой порядка байтов.

Любые другие имеющиеся у вас инструменты для работы со скриптами PowerShell могут зависеть от выбранных параметров кодировки или преобразовывать скрипты в другую кодировку.

Существующие скрипты

Скрипты, которые уже находятся в файловой системе, могут нуждаться в повторном кодировании в указанную вами кодировку. В нижней строке VS Code вы увидите метку UTF-8. Щелкните ее, чтобы открыть панель действий, и выберите команду Сохранить с кодировкой. Теперь вы можете выбрать новую кодировку для этого файла. Подробные инструкции см. в разделе Кодировка в VS Code.

Если вам нужно повторно кодировать несколько файлов, можно использовать следующий скрипт:

Интегрированная среда сценариев (ISE) PowerShell

При редактировании скриптов с помощью интегрированной среды сценариев PowerShell необходимо синхронизировать здесь параметры кодировки.

Интегрированная среда сценариев должна учитывать метку порядка байтов, но можно также использовать отражение для задания кодировки. Обратите внимание, что это значение не сохраняется между запусками.

Система управления версиями

Некоторые системы управления версиями, например git, игнорируют кодировки; git отслеживает только байты. Поведение других, например Azure DevOps или Mercurial, может отличаться. Даже некоторые средства, основанные на git, полагаются на декодирование текста.

Если это так, убедитесь, что вы:

  • Настроили кодировку в системе управления версиями в соответствии с вашей конфигурацией VS Code.
  • Сделали так, что все файлы добавляются в систему управления версиями в соответствующей кодировке.
  • Остерегайтесь изменять кодировки, полученные через систему управления версиями. Ключевым признаком здесь будет разностный файл, который указывает, что изменения отсутствуют (так как изменены байты, но не символы).

Среды других участников

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

Другие программы

Все другие программы, которые считывают или записывают скрипты PowerShell, могут перекодировать их.

  • Использование буфера обмена для копирования и вставки скрипта. Такое часто встречается в следующих случаях:
    • Копирование скрипта в виртуальную машину.
    • Копирование скрипта из электронной почты или с веб-страницы.
    • Копирование скрипта через документ Microsoft Word или PowerPoint.
    • Блокнот;
    • vim;
    • любой другой редактор скриптов PowerShell.
    • Get-Content / Set-Content / Out-File
    • Операторы перенаправления PowerShell, такие как > и >> .
    • sed / awk
    • Веб-браузер при скачивании скриптов.
    • Общий файловый ресурс.

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

    Другие ресурсы о кодировках в PowerShell

    Существует несколько других достойных публикаций на тему кодировок и настройки кодирования в PowerShell:

    Описывает, как PowerShell использует кодировку символов для ввода и вывода строковых данных.

    Подробное описание

    Юникод — это мировой стандарт кодировки символов. Система использует Юникод исключительно для обработки символов и строк. Подробное описание всех аспектов Юникода см. в стандарте Юникода.

    По умолчанию PowerShell использует набор символов Юникода. Однако несколько командлетов имеют параметр кодирования , который может указывать кодировку для другой кодировки. Этот параметр позволяет выбрать конкретную кодировку символов, необходимую для взаимодействия с другими системами и приложениями.

    Следующие командлеты имеют параметр Encoding :

    • Microsoft.PowerShell.Management
      • Add-Content
      • Get-Content
      • Set-Content
      • Export-Clixml
      • Export-Csv
      • Export-PSSession
      • Format-Hex
      • Import-Csv
      • Out-File
      • Select-String
      • Send-MailMessage

      Пометка порядка байтов

      Символ-пометка (BOM) — это сигнатура в Юникоде в первых нескольких байтах файла или текстового потока, указывающих, какая кодировка Юникода используется для данных. Дополнительные сведения см. в документации по метке порядка байтов .

      в Windows PowerShell любая кодировка юникода, за исключением UTF7 , всегда создает спецификацию. PowerShell (V6 и более поздние версии) по умолчанию имеет значение utf8NoBOM для всех текстовых выходных данных.

      Для обеспечения оптимальной совместимости Избегайте использования спецификаций в файлах UTF-8. платформы unix и служебные программы unix-heritage, также используемые на платформах Windows, не поддерживают спецификации.

      Аналогичным образом UTF7 следует избегать кодирования. UTF-7 не является стандартной кодировкой Юникода и записывается без спецификации во всех версиях PowerShell.

      создание сценариев PowerShell на платформе, похожем на Unix, или использовании кросс-платформенного редактора на Windows, например Visual Studio Code, приводит к созданию файла, закодированного с помощью UTF8NoBOM . эти файлы прекрасно работают в PowerShell, но могут нарушить работу Windows PowerShell если файл содержит символы, отличные от Ascii.

      Если в скриптах необходимо использовать символы, отличные от ASCII, сохраните их как UTF-8 с помощью BOM. без спецификации Windows PowerShell правильно интерпретирует скрипт как закодированный в устаревшей кодовой странице ANSI. И наоборот, файлы, имеющие СПЕЦИФИКАЦИю UTF-8, могут быть проблематичными для платформ, подобных Unix. Многие средства UNIX, такие как cat ,, sed awk и некоторые редакторы, например, gedit не узнают, как обрабатывать спецификацию.

      Кодировка символов в Windows PowerShell

      В PowerShell 5,1 параметр Encoding поддерживает следующие значения:

      • Ascii Использует кодировку ASCII (7-разрядных).
      • BigEndianUnicode Использует UTF-16 с обратным порядком байтов.
      • BigEndianUTF32 Использует UTF-32 с обратным порядком байтов.
      • Byte Кодирует набор символов в последовательность байтов.
      • Default Использует кодировку, соответствующую активной кодовой странице системы (обычно ANSI).
      • Oem Использует кодировку, соответствующую текущей кодовой странице OEM системы.
      • String аналогичен Unicode .
      • Unicode Использует UTF-16 с прямым порядком байтов.
      • Unknown аналогичен Unicode .
      • UTF32 Использует UTF-32 с прямым порядком байтов.
      • UTF7 Использует UTF-7.
      • UTF8 Использует UTF-8 (с BOM).

      в общем случае Windows PowerShell по умолчанию использует кодировку юникод UTF-16le . однако кодировка по умолчанию, используемая командлетами в Windows PowerShell, не согласуется.

      При использовании любой кодировки Юникода, за исключением UTF7 , всегда создает спецификацию.

      Для командлетов, записывающих выходные данные в файлы:

      Out-File и операторы перенаправления > и >> создают UTF-16LE, который, в свою очередь, отличается от Set-Content и Add-Content .

      New-ModuleManifest а Export-CliXml также создавать файлы UTF-16LE.

      Если целевой файл пуст или не существует, Set-Content и Add-Content Используйте Default кодировку. Default — это кодировка, определяемая кодовой страницей устаревшей версии ANSI на языке активного системы.

      Export-Csv создает Ascii файлы, но использует другую кодировку при использовании параметра append (см. ниже).

      Export-PSSession по умолчанию создает файлы UTF-8 с BOM.

      New-Item -Type File -Value создает файл UTF-8 с кодировкой BOM.

      Send-MailMessage по Default умолчанию использует кодировку.

      Start-Transcript создает Utf8 файлы с помощью спецификации. При использовании параметра append кодировка может отличаться (см. ниже).

      Для команд, которые добавляют к существующему файлу:

      Out-File -Append и >> оператор перенаправления не пытается сопоставить кодировку содержимого существующего целевого файла. Вместо этого они используют кодировку по умолчанию, если не используется параметр Encoding . При добавлении содержимого необходимо использовать исходную кодировку файлов.

      При отсутствии явного параметра кодировки Add-Content обнаруживает существующую кодировку и автоматически применяет ее к новому содержимому. Если имеющееся содержимое не имеет BOM, Default используется кодировка ANSI. Поведение функции Add-Content аналогично в PowerShell (V6 и более поздних версиях), за исключением кодировки по умолчанию — Utf8 .

      Export-Csv -Append соответствует существующей кодировке, если целевой файл содержит СПЕЦИФИКАЦИю. В отсутствие спецификации используется Utf8 Кодировка.

      Start-Transcript -Append соответствует существующей кодировке файлов, включающих СПЕЦИФИКАЦИю. При отсутствии спецификации по умолчанию используется Ascii Кодировка. Такая кодировка может привести к утере данных или повреждению символов, если данные в записи содержат многобайтовые символы.

      Для командлетов, считывающих строковые данные в отсутствие спецификации:

      Get-Content и Import-PowerShellDataFile использует Default кодировку ANSI. ANSI также используется механизмом PowerShell при чтении исходного кода из файлов.

      Import-Csv , Import-CliXml и Select-String предполагают Utf8 отсутствие спецификации.

      Кодировка символов в PowerShell

      В PowerShell (V6 и более поздних версий) параметр Encoding поддерживает следующие значения:

      • ascii : Использует кодировку для набора символов ASCII (7-разрядных).
      • bigendianunicode : Кодируется в формате UTF-16 с обратным порядком байтов.
      • oem : Использует кодировку по умолчанию для программ MS-DOS и консолей.
      • unicode : Кодируется в формате UTF-16 с прямым порядком байтов.
      • utf7 : Кодируется в формате UTF-7.
      • utf8 : Кодирует в формате UTF-8 (без спецификации).
      • utf8BOM : Кодирует в формате UTF-8 с меткой порядка байтов (BOM)
      • utf8NoBOM : Кодирует в формате UTF-8 без метки порядка байтов (BOM)
      • utf32 : Кодируется в формате UTF-32.

      По умолчанию PowerShell принимает значение utf8NoBOM для всех выходных данных.

      Изменение кодировки по умолчанию

      В PowerShell есть две переменные по умолчанию, которые можно использовать для изменения поведения кодировки по умолчанию.

      • $PSDefaultParameterValues
      • $OutputEncoding

      Дополнительные сведения см. в разделе about_Preference_Variables.

      Начиная с PowerShell 5,1, операторы перенаправления ( > и >> ) вызывают Out-File командлет. Таким образом, можно задать кодировку по умолчанию для них с помощью $PSDefaultParameterValues переменной предпочтений, как показано в следующем примере:

      Используйте следующую инструкцию, чтобы изменить кодировку по умолчанию для всех командлетов, имеющих параметр Encoding .

      При размещении этой команды в профиле PowerShell предпочтение влияет на глобальные параметры сеанса, влияющие на все команды и скрипты, которые явно не задают кодировку.

      Аналогичным образом следует включить такие команды в скрипты или модули, которые должны вести себя одинаково. Использование этих команд гарантирует, что командлеты ведут себя одинаково даже при запуске другого пользователя, на другом компьютере или в другой версии PowerShell.

      Автоматическая переменная $OutputEncoding влияет на кодирование, используемое PowerShell для взаимодействия с внешними программами. Он не влияет на кодировку, которую операторы перенаправления вывода и командлеты PowerShell используют для сохранения в файлах.

      По умолчанию, когда вы перенаправляете вывод команды в файл или перенаправляете его во что-то еще в PowerShell, используется кодировка UTF-16, что бесполезно. Я хочу изменить его на UTF-8.

      Это можно сделать в каждом конкретном случае, заменив синтаксис >foo.txt на | out-file foo.txt -encoding utf8 , но это неудобно повторять каждый раз.

      Постоянный способ настроить вещи в PowerShell - это поместить их в \Users\me\Documents\WindowsPowerShell\profile.ps1 ; Я убедился, что этот файл действительно запускается при запуске.

      Было сказано, что кодировку вывода можно установить с помощью $PSDefaultParameterValues = @ , но я пробовал это, и это не помогло.

      Как настроить PowerShell на использование UTF-8?

      2 ответа

      Примечание. Следующее относится к Windows PowerShell .
      См. следующий раздел о кроссплатформенной версии PowerShell Core (v6 +) .

      В PSv5.1 или более поздней версии , где > и >> фактически являются псевдонимами Out-File , вы можете установить кодировку по умолчанию для > / >> / Out-File через предпочтительную переменную $PSDefaultParameterValues :

      • $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'

      В версии PSv5.0 или ниже вы не можете изменить кодировку для > / >> , но в PSv3 или выше , описанный выше метод действительно работает для явных вызовов Out-File .
      (Переменная предпочтения $PSDefaultParameterValues была введена в PSv3.0).

      В PSv3.0 или более поздней версии , если вы хотите установить кодировку по умолчанию для всех командлетов, поддерживающих
      параметр -Encoding (который в PSv5.1 + включает > и >> ), используйте:

      Если вы поместите эту команду в свой $PROFILE , такие командлеты, как Out-File и Set-Content , по умолчанию будут использовать кодировку UTF-8, но обратите внимание, что это делает его глобальным параметром сеанса , который будет влиять на все команды / сценарии, в которых явно не указана кодировка.

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

      Предостережение : ** PowerShell, начиная с версии 5.1, неизменно создает файлы UTF-8 _с (псевдо) BOM _ **, который используется только в мире Windows - Unix - Утилиты на базе не распознают эту спецификацию (см. внизу); см. этот пост для обходных путей, которые создают файлы UTF-8 без спецификации.

      Для получения сводки о крайне несовместимом кодировке символов по умолчанию во многих стандартных командлетах Windows PowerShell см. Нижний раздел.

      Автоматическая переменная $OutputEncoding не связана и применяется только к тому, как PowerShell взаимодействует с внешними программами (какую кодировку использует PowerShell при отправке строк к ним) - это не имеет ничего общего с кодировкой, которую операторы перенаправления вывода и командлеты PowerShell используют для сохранения в файлы.

      Дополнительное чтение: кросс-платформенная перспектива: PowerShell Core :

      теперь в PowerShell кросс-платформенный через его PowerShell Core , чья кодировка - разумно - по умолчанию - UTF-8 без спецификации в соответствии с Unix-подобными платформами.

      Это означает, что файлы исходного кода без спецификации считаются UTF-8, а при использовании > / Out-File / Set-Content по умолчанию используется без спецификации UTF. -8; явное использование аргумента utf8 -Encoding также создает без спецификации UTF-8, но вы можете выбрать создание файлов с псевдо-спецификацией со значением utf8bom .

      Если вы создаете сценарии PowerShell с помощью редактора на Unix-подобной платформе, а в настоящее время даже в Windows с кросс-платформенными редакторами, такими как Visual Studio Code и Sublime Text, результирующий файл *.ps1 обычно будет без псевдо-спецификации UTF-8:

      • Это отлично работает в PowerShell Core .
      • Он может сломаться в Windows PowerShell , если файл содержит символы, отличные от ASCII; если вам действительно нужно использовать в скриптах символы, отличные от ASCII, сохраните их как UTF-8 с спецификацией .
        Без спецификации Windows PowerShell (неправильно) интерпретирует ваш скрипт как закодированный в устаревшей кодовой странице «ANSI» (определяемой языковым стандартом системы для приложений, предшествующих Unicode; например, Windows-1252 в системах на английском языке).

      И наоборот, файлы, которые имеют псевдо-спецификацию UTF-8, могут быть проблематичными на Unix-подобных платформах, так как они вызывают такие утилиты Unix, как cat , sed и < > - и даже некоторые редакторы, такие как gedit - для передачи псевдо-спецификации , т. Е. Для обработки ее как данных .

      • Это может не всегда быть проблемой, но определенно может быть, например, когда вы пытаетесь прочитать файл в строке в bash , скажем, text=$(cat file) или text=$(<file) - результирующая переменная будет содержать псевдо-спецификацию в качестве первых 3 байтов.

      Несогласованное поведение кодировки по умолчанию в Windows PowerShell :

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

      Нижеследующее не претендует на охват всех стандартных командлетов.

      Поиск в Google имен командлетов для поиска их разделов справки теперь по умолчанию показывает версию тем PowerShell Core ; используйте раскрывающийся список версий над списком тем слева, чтобы переключиться на версию Windows PowerShell .

      На момент написания этой статьи в документации часто неверно утверждается, что ASCII является кодировкой по умолчанию в Windows PowerShell - см. эта проблема с документами GitHub .

      Командлеты, пишущие :

      Out-File и > / >> создают "Unicode" - UTF-16LE - файлы по умолчанию, в которых каждый символ диапазона ASCII (тоже) представлен 2 байтами, что заметно отличается от Set-Content / Add-Content (см. следующий пункт); New-ModuleManifest и Export-CliXml также создают файлы UTF-16LE.

      Set-Content (и Add-Content , если файл еще не существует / пуст) использует кодировку ANSI (кодировку, указанную устаревшей кодовой страницей ANSI активного языкового стандарта, которую PowerShell вызывает Default ) .

      Export-Csv действительно создает файлы ASCII, как описано в документации, но см. Примечания относительно -Append ниже.

      Export-PSSession по умолчанию создает файлы UTF-8 со спецификацией.

      New-Item -Type File -Value в настоящее время создает (!) UTF-8 без спецификации.

      В разделе справки Send-MailMessage также утверждается, что по умолчанию используется кодировка ASCII - я лично не проверял это утверждение.

      Start-Transcript неизменно создает файлы UTF-8 с спецификацией, но см. Примечания относительно -Append ниже.

      Команды Re, которые добавляют к существующему файлу:

      >> / Out-File -Append не предпринимают никаких попыток сопоставить кодировку существующего содержимого файла . То есть они вслепую применяют свою кодировку по умолчанию, если иное не указано с помощью -Encoding , что невозможно с >> (кроме косвенного в PSv5.1 +, через $PSDefaultParameterValues , как показано выше ). Вкратце: вы должны знать кодировку содержимого существующего файла и добавлять его, используя ту же кодировку.

      Add-Content - похвальное исключение: в отсутствие явного аргумента -Encoding он определяет существующую кодировку и автоматически применяет ее к новому контенту. Спасибо, js2010 . Обратите внимание, что в Windows PowerShell это означает, что применяется кодировка ANSI, если существующее содержимое не имеет спецификации, тогда как в PowerShell Core используется кодировка UTF-8.

      Это несоответствие между Out-File -Append / >> и Add-Content , которое также влияет на PowerShell Core , обсуждается в эта проблема GitHub.

      Export-Csv -Append частично соответствует существующей кодировке: он слепо добавляет UTF-8 , если кодировка существующего файла является любой из ASCII / UTF-8 / ANSI, но правильно соответствует UTF-16LE и UTF-16BE.
      Иными словами: при отсутствии спецификации Export-Csv -Append предполагает UTF-8, тогда как Add-Content предполагает ANSI.

      Start-Transcript -Append частично соответствует существующей кодировке: она правильно соответствует кодировкам с спецификацией , но по умолчанию используется кодировка ASCII с потенциально потерями при ее отсутствии.

      Командлеты, которые читают (то есть кодировку, используемую при отсутствии спецификации ):

      Get-Content и Import-PowerShellDataFile по умолчанию - ANSI ( Default ), что соответствует Set-Content .
      ANSI - это также то, что сам движок PowerShell по умолчанию использует при чтении исходного кода из файлов.

      Напротив, Import-Csv , Import-CliXml и Select-String предполагают UTF-8 при отсутствии спецификации.

      Читайте также: