ответ js2010 обеспечивает эффективное решение; позвольте мне дополнить его справочной информацией (краткое описание рассматриваемого дела находится внизу):
По существу, PowerShell никогда сохраняет кодировку символов входного файла [текст] на выходе :
при чтение , содержимое файла декодировано в. NET строки (которые являются внутренними единицами кода UTF-16):
Файлы с спецификацией для следующих кодировок всегда правильно распознаются (идентификаторы, распознаваемые параметром -Encoding
командлетов PowerShell в скобках):
- UTF-8 (
UTF8
) - info - UTF-16LE (
Unicode
) / UTF-16BE (BigEndianUnicode
) - info - UTF-32LE (
UTF32
) / UTF-32BE (BigEndianUTF32
) - info - Обратите внимание на отсутствие UTF-7 , которое, однако, на практике редко используется в качестве кодировки.
Без Спецификация , по умолчанию предполагается кодировка :
- PowerShell [Core] v6 + похвально предполагает UTF-8 .
- Устаревшая Windows PowerShell (PowerShell до v5.1) предполагает кодирование ANSI , то есть кодовую страницу, определяемую языковой версией устаревшей системы; например, Windows -1252 в системах US-Engli sh.
Параметр -Encoding
командлетов для чтения файлов позволяет вам явно указывает исходную кодировку , но учтите, что наличие (поддерживаемой) спецификации переопределяет this - сведения о поддерживаемых кодировках см. Ниже.
При записи ,. NET строки кодируются на основе кодировки по умолчанию , если только кодировка явно не указана с помощью -Encoding
(строки. NET, созданные при чтении, не содержат никакой информации о кодировке исходного входного файла, поэтому ее нельзя сохранить):
PowerShell [Core] v6 + похвально использует без спецификации UTF-8 .
Наследие Windows PowerShell (PowerShell до v5.1), к сожалению использует различные кодировки по умолчанию, в зависимости от конкретного использования c командлета / оператора d .
Примечательно, что Set-Content
по умолчанию соответствует ANSI (для чтения) и Out-File
/ >
по умолчанию UTF-16LE .
Как отмечено в ответе js2010 с использованием -Encoding UTF8
в Windows PowerShell неизменно создает файлы с спецификацией , что может быть проблематичным c для файлов, считываемых инструментами на Unix платформы / инструменты с Unix наследием, которые часто не оснащены для работы с такой спецификацией.
- См. ответы на этот вопрос , чтобы узнать, как создать без спецификации. Файлы UTF-8 в Windows PowerShell.
Как и при чтении, параметр -Encoding
записи в файл Командлеты позволяют явно указывать выходную кодировку :
Обратите внимание, что в PowerShell [Core] v6 +, в дополнение к по умолчанию для спецификации без UTF-8, -Encoding UTF8
тоже относится к т вариант без спецификации (в отличие от Windows PowerShell), и там вы должны использовать -Encoding UTF8BOM
для создания файла с спецификацией.
Любопытно Начиная с PowerShell [Core] v7.0, для активной кодовой страницы ANSI системы есть значение no -Encoding
, то есть для Windows PowerShell по умолчанию (в Windows PowerShell, -Encoding Default
явно запрашивать кодировку ANSI, но в PowerShell [Core] это относится к UTF-8 без спецификации). Это проблемное c упущение обсуждается в этом выпуске GitHub . Напротив, нацеливание на активную кодовую страницу OEM с -Encoding OEM
все еще работает.
Для создания файлов UTF-32BE Windows PowerShell требуется идентификатор BigEndianUtf32
; из-за ошибки в PowerShell [Core] начиная с версии 7.0 этот идентификатор не поддерживается, но вместо него можно использовать UTF-32BE
.
Windows PowerShell ограничен теми кодировками, которые перечислены в перечислении Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding
, но PowerShell [Core] позволяет передавать любой из поддерживаемых . NET кодирование в -Encoding
параметр либо по номеру кодовой страницы (например, 1252
), либо по имени кодировки (например, windows-1252
); [Text.Encoding]::GetEncodings().CodePage
и [Text.Encoding]::GetEncodings().Name
перечисляют их в принципе, но учтите, что из-за отсутствия. NET поддержки Core API с версии v7.0 это перечисление перечисляет только небольшое подмножество фактически поддерживаемых кодировок; выполнение этих команд в Windows PowerShell покажет их все.
Вы можете создавать файлы UTF-7 (UTF7
), но они не будут иметь спецификацию; даже входные файлы, у которых они есть, не распознаются автоматически при чтении, поэтому указание -Encoding UTF7
равно всегда , необходимое для чтения файлов UTF-7.
Вкратце:
В PowerShell необходимо знать кодировку входного файла, чтобы соответствовать этому кодирование при записи и укажите, что кодировка явно через параметр -Encoding
(если он отличается от значения по умолчанию).
Get-Content
(без -Encoding
) обеспечивает нет информация о том, какую кодировку он обнаружил через спецификацию или какую кодировку он предположил в отсутствие спецификации.
При необходимости вы можете выполнить собственный анализ начальные байты текстового файла для поиска спецификации, но учтите, что при отсутствии таковой вам придется полагаться на эвристику до выводить кодировку - то есть вы может сделать разумное предположение, но вы не можете быть уверены.
Также обратите внимание, что Пау В rShell, начиная с v7, принципиально отсутствует поддержка прохождения необработанных потоков байтов через конвейер - см. этот ответ .
Ваш конкретный случай :
Ваша проблема заключалась в том, что ваш входной файл был в кодировке UTF-8, но не имел спецификации (что на самом деле предпочтительнее для самой широкой совместимости).
Поскольку вы используете Windows PowerShell , который неправильно интерпретирует такие файлы, как кодированные в ANSI, вы должны указать ему прочитать файл как UTF-8 с -Encoding Utf8
.
Как указано, при записи -Encoding Utf8
неизбежно создает файл с спецификацией в Windows PowerShell; если это вызывает озабоченность, используйте платформу. NET напрямую для создания файлов без спецификации, как показано в ответах на этот вопрос .
Обратите внимание, что вы бы у нет проблемы с исходной командой в PowerShell [Core] v6 + - по умолчанию используется UTF-8 без спецификации как для чтения, так и для записи во всех командлетах.
Одно только это разумное стандартизированное значение по умолчанию является хорошей причиной для рассмотрения перехода на PowerShell v7.0, который призван стать превосходной заменой устаревшей Windows PowerShell.