Змінення вихідного кодування PowerShell за замовчуванням на UTF-8


106

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

Це можна зробити в кожному конкретному випадку, замінивши >foo.txtсинтаксис на, | out-file foo.txt -encoding utf8але це незручно повторювати щоразу.

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

Було сказано, що вихідне кодування можна встановити за допомогою, $PSDefaultParameterValues = @{'Out-File:Encoding' = 'utf8'}але я спробував це, і це не мало ніякого ефекту.

https://blogs.msdn.microsoft.com/powershell/2006/12/11/outputencoding-to-the-rescue/, де йдеться про те, що $OutputEncodingна перший погляд виглядає так, ніби це повинно бути релевантним, але потім йдеться про кодування виводу в ASCII, що насправді не відбувається.

Як налаштувати PowerShell на використання UTF-8?

Відповіді:


164

Примітка: Наступне стосується 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 + включає в себе >і >>), використовуйте:

    • $PSDefaultParameterValues['*:Encoding'] = 'utf8'

Якщо ви розміщуєте цю команду у своїх$PROFILE командлетах, таких як Out-FileіSet-Content використовуватимуть кодування UTF-8 за замовчуванням, але зверніть увагу, що це робить це глобальне налаштування сеансу, яке впливатиме на всі команди / сценарії, які явно не вказують кодування.

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

Увага : ** PowerShell, починаючи з версії 5.1, незмінно створює файли UTF-8 з (псевдо) специфікацією _ ** , що є звичним лише у світі Windows - утиліти на базі Unix не розпізнають цю специфікацію (див. Внизу); див. цю публікацію щодо обхідних шляхів, що створюють файли UTF-8 без спеціальних специфікацій.

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


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


Необов’язкове читання: Перспектива між платформами: Ядро PowerShell :

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 псевдо-BOM може бути проблематичним , на Unix-подібних платформах, так як вони викликають Unix утиліт , таких як cat, sedі awk- і навіть деякі редактори , такі як gedit- щоб передати псевдо-BOM через , тобто розглядати це як дані .

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

Невідповідна поведінка кодування за замовчуванням у Windows PowerShell :

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

Примітка:

  • Наведене не прагне охоплювати всі стандартні командлети.

  • Прогугливання імен командлетів для пошуку тем довідки тепер показує версію тем 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-ContentAdd-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, якщо існуючий вміст не має специфікації, тоді як це UTF-8 у PowerShell Core.

Ця невідповідність між 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 під час відсутності специфікації.


Чи можете ви пояснити, як >/ >>стали ефективними псевдоніми для Out-File5.1?
Максиміліан Бурслі

@ TheIncorrigible1: Можливо, це вказав мені PetSerAl, але я не пам’ятаю, де і як. Windows PowerShell є закритим вихідним кодом, але оскільки ті самі відносини з квазіаліасом стосуються і PowerShell Core, ви зможете знайти його у вихідному коді останнього.
mklement0,

2
Я не погоджуюсь, @EliaWeiss, але це конкретно Windows PowerShell, і вони врешті-решт зрозуміли це прямо в PowerShell Core .
mklement0,

2
@Marc: VS Code та інші сучасні крос-платформні редактори похвалимо за замовчуванням UTF-8, що, однак, означає, що вони неправильно інтерпретують файли, кодовані ANSI. Блокнот використовує евристику для вгадування кодування. Справа в тому, що це лише здогадки , оскільки будь-який файл, кодований UTF-8, також є технічно допустимим файлом, кодованим ANSI (але не навпаки). Було б чудово, якби все в Windows за замовчуванням було UTF-8 за відсутності специфікації, як це роблять Unix-подібні платформи, але це не так, зокрема, не в Windows PowerShell, хоча, на щастя, зараз це стосується PowerShell Core.
mklement0

2
Щоб переглянути ваше поточне значення, якщо якесь, просто введіть$PSDefaultParameterValues
Sandburg

3

Якщо коротко, використовуйте:

write-output "your text" | out-file -append -encoding utf8 "filename"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.